ACdream 1083人民城管爱人民

来源:互联网 发布:xy网络流行什么意思 编辑:程序博客网 时间:2024/04/27 08:25

Description

一天GG正在和他的后宫之一的MM在外面溜达,MM突然说了一句,“我想吃鸡蛋灌饼”……当他们吃的正high的时候,城管出现了!作为传说中的最强军事力量,卖鸡蛋灌饼的小贩在他们面前也只算是战力为的5的渣滓,一秒钟就被秒杀了……

在这场屠杀中,GG和他的后宫本来只是围观群众,但是不幸的是,城管看到了GG胃里的鸡蛋灌饼,他们要逮捕GG!但是GG显然不能让他们如愿,于是GG带着后宫开始了往大运村的逃亡之旅。

整个地图有n个路口,灌饼摊在0号路口,大运村在n-1号路口。有m条只能单向通过的道路连接这n个路口,每条道路用一个正整数表示走过需要的时间。整个地图没有环路,但两个路口之间可能有多条通路。现在GG希望以最短的时间到大运村,但不幸的是,城管为了抓住他动用了卫星对他进行空中跟踪,并且会在某一时刻空降到某一条道路上进行封锁(封锁会在瞬间完成,可惜动静太大了GG也能在第一时间知道哪条道路被封锁了),之后这条路就无法通过了。在整个行动中只会出现一次空降,而且不会在GG经过这条道路的时候进行封锁,也就是说,不会在GG在某条路上走了一半的时候封锁这条路。而且,城管们希望尽可能的延缓GG到达大运村的时间。

现在GG希望知道,自己多久能到达大运村,方便安排之后和其他后宫的约会。

注意双方是以博弈的思想来进行选择,即GG希望时间最短,城管希望时间最长,而且他们都非常聪明会做出最佳的选择。

Input

输入第一行为数据组数T(T<=30)。

每组数据第一行包含两个整数n,m(2<=n<=10000,1<=m<=100000),表示路口数和道路数。之后m行描述了所有的道路,每行有三个整数u,v,w(0<=u,v<n,0<w<=1000),表示路口u到路口v有一条需要w时间走过的道路。

Output

对于每组数据输出一个整数,表示GG最后到达大运村需要的时间。如果GG无法到达大运村,输出-1。

Sample Input

25 60 1 11 2 12 4 11 4 30 3 23 4 13 40 1 10 1 21 2 31 2 4

Sample Output

45


DAG图,先进行拓扑排序,得到序列,然后进行dp,考虑删边的操作在什么地方进行。

dp[i]表示从i这里开始删边,g[i]表示从i到n的最优值和次优值。

#include<set>#include<map>#include<ctime>#include<cmath>#include<stack>#include<queue>#include<bitset>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>#include<functional>#define rep(i,j,k) for (int i = j; i <= k; i++)#define per(i,j,k) for (int i = j; i >= k; i--)#define loop(i,j,k) for (int i = j;i != -1; i = k[i])#define lson x << 1, l, mid#define rson x << 1 | 1, mid + 1, r#define fi first#define se second#define mp(i,j) make_pair(i,j)#define pii pair<int,int>using namespace std;typedef long long LL;const int low(int x) { return x&-x; }const double eps = 1e-8;const int INF = (1 << 30) - 1;const int mod = 10000;const int N = 2e5 + 10;const int read(){char ch = getchar();while (ch<'0' || ch>'9') ch = getchar();int x = ch - '0';while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';return x;}int T, n, m, x, y, z;int ft[N], nt[N], u[N], v[N], sz;int FT[N], NT[N], U[N], V[N], ct[N];int a[N], g[N][2], dp[N];int main(){T = read();while (T--){scanf("%d%d", &n, &m);sz = 0;rep(i, 1, n) ft[i] = FT[i] = -1, ct[i] = dp[i] = 0;rep(i, 1, m){scanf("%d%d%d", &x, &y, &z);++x;++y;ct[x]++;u[sz] = y;v[sz] = z; nt[sz] = ft[x];ft[x] = sz;U[sz] = x;V[sz] = z; NT[sz] = FT[y];FT[y] = sz++;  }queue<int>p;int t = 0;rep(i, 1, n) if (!ct[i]) p.push(i);rep(i, 1, n) g[i][0] = g[i][1] = INF;g[n][0] = g[n][1] = 0;while (!p.empty()){a[++t] = p.front();p.pop();loop(i, FT[a[t]], NT){if (!(--ct[U[i]])) p.push(U[i]);if (g[a[t]][0] == INF) continue;g[U[i]][1] = min(g[U[i]][1], g[a[t]][0] + V[i]);if (g[U[i]][1] < g[U[i]][0]) swap(g[U[i]][0], g[U[i]][1]);}}rep(i, 1, n){int x = a[i];if (x == n) { dp[x] = 0; continue; }dp[x] = INF;loop(j, ft[x], nt){if (g[u[j]][0] + v[j] == g[x][0]) dp[x] = min(dp[x], max(g[x][1], dp[u[j]] + v[j]));else dp[x] = min(dp[x], max(g[x][0], dp[u[j]] + v[j]));}}printf("%d\n", dp[1] >= INF ? -1 : dp[1]);}return 0;}


0 0
原创粉丝点击