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;}