思路:d(i, 0)表示从节点i到达大运村的最短路径,d(i, 1)表示从节点i到达大运村的次短路径。

1.最短路:当做DAG处理即可。

2.次短路:假设当前在u点处,下一个节点是v。v到终点的最短路是d(v, 0),次短路是d(v, 1),u到v的距离是w(u, v),只能封锁一条路,即只能删除一条边。分成两种情况:

a.将封锁用在了v点到达终点的路上,则此时GG拥有主动权,可以选择最小的路径,即Imin = min(w(u, v) + d(v, 1)),;

b.将封锁用在u-v这条路径上面,则此时城管拥有主动权,可以封锁最短路径,则GG这能选择次短路径Hmin。

则d(u, 1) = max(Imin, Hmin)

AC代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 10000 + 5;
int n, m;
int d[maxn][2], in[maxn], Top[maxn], c[maxn*20];

struct Edge{
	int from, to, dist, nex;
	Edge() {}
	Edge(int u, int v, int d, int ne):from(u), to(v), dist(d), nex(ne){}
}edge[maxn*20];

int edgenum, head[maxn];
void add_edge(int u, int v, int dis) {
	edge[edgenum] = Edge(u, v, dis, head[u]);
	head[u] = edgenum++;
}

void topsort() { //逆向拓扑序
	queue<int>q;
	for(int i = 0; i < n; ++i) if(!in[i]) q.push(i);
	int num = 0;
	while(!q.empty()) {
		int u = q.front(); q.pop();
		for(int i = head[u]; i != -1; i = edge[i].nex) if(i&1){
			int v = edge[i].to;
			--in[v];
			if(!in[v]) q.push(v);
		}
		Top[num++] = u;
	}
}

void solve(int u) {
	if(u == n-1) {d[u][0] = d[u][1] = 0; return;} //终点
	int num = 0, Imin = inf;
	for(int i = head[u]; i != -1; i = edge[i].nex) if(!(i&1)){
		int v = edge[i].to;
		//最短路
		d[u][0] = min(d[u][0], d[v][0] + edge[i].dist);
		//次短路
		Imin = min(Imin, d[v][1] + edge[i].dist); // GG掌握主动权
		c[num++] = d[v][0] + edge[i].dist; //城管有主动权
	}
	if(num < 2) {d[u][1] = inf; return;} //GG无法到达从u到达终点
	int fir = c[0], sec = c[1]; //最小和次小
	if(fir > sec) swap(fir, sec);
	for(int i = 2; i < num; ++i) {
		if(c[i] <= fir) {
			sec = fir;
			fir = c[i];
		}
		else sec = min(sec, c[i]);
	}
	d[u][1] = max(Imin, sec);
	if(d[u][1] > inf) d[u][1] = inf;
	if(d[u][0] > inf) d[u][0] = inf;
}

int main() {
	int T;
	scanf("%d", &T);
	while(T--) {
		edgenum = 0;
		memset(head, -1, sizeof(head));
		memset(d, inf, sizeof(d));
		memset(in, 0, sizeof(in));
		scanf("%d%d", &n, &m);
		int u, v, dis;
		for(int i = 0; i < m; ++i) {
			scanf("%d%d%d", &u, &v, &dis);
			add_edge(u, v, dis);
			add_edge(v, u, dis);
			in[u]++;
		}
		topsort();
		for(int i = 0; i < n; ++i) {
			solve(Top[i]);
		}
		if(d[0][1] >= inf) printf("-1\n");
		else printf("%d\n", d[0][1]);
	}
	return 0;
} 

如有不当之处欢迎指出!

最新文章

  1. WCF 实体更改发布后,如何不影响调用方?
  2. [原创]C++通用宏定义
  3. agularJs 路由
  4. lua中常量的实现及表的深拷贝实现
  5. 【测试】使用hr用户下的employees和departments表写一条SQL语句,(MG连接)
  6. shell脚本的入参
  7. PHP pear安装出现 Warning: require_once(Structures/Graph.php)...错误
  8. Foj1675数论
  9. [置顶] 使用Android OpenGL ES 2.0绘图之六:响应触摸事件
  10. MariaDB GTID 复制同步
  11. 【Mybatis】配置文件加载属性
  12. Linux入门之常用命令(6)Bash命令重定向 管线命令
  13. LeetCode &amp; Q121-Best Time to Buy and Sell Stock-Easy
  14. 【一天一道LeetCode】#93. Restore IP Addresses
  15. infiniDB无法建表
  16. 利用VMWare 11 在 Windows 8.1 下安装与优化 OS X 10.10
  17. Shell 简单构建 Node web服务器
  18. HDU 3306 Another kind of Fibonacci(矩阵+ll超时必须用int&amp;输入必须取模&amp;M必须是int类型)
  19. Python单元测试框架之pytest 3 -- fixtures
  20. bootstrap3中select2的默认值和下拉框的禁用

热门文章

  1. 如何用docker部署redis cluster
  2. RadioButton与监听
  3. GTID复制详解
  4. Android 初了解
  5. linux的8小时差问题解决
  6. 使用FileReader实现前端预览所选图片
  7. 如何让oracle DB、监听和oem开机启动(dbstart)
  8. Scrapy框架实战-妹子图爬虫
  9. Asp.net core Razor 页面
  10. linux打印彩色字