题意:
在无向图上删边,让此图上从起点到终点的最短路长度变大,删边的代价是边长,求最小代价。
题解:
先跑一遍迪杰斯特拉,求出所有点的d[]值,然后在原图上保留所有的边(i,j)仅当i,j满足d[j]-d[i]=l(i,j),在这个图上跑最小割。
时间复杂度O((E)logV+V^2*E)
#include <bits/stdc++.h> #pragma GCC optimize(2) using namespace std; typedef long long LL; #define ls (rt<<1) #define rs (rt<<1|1) const int M = 1e5 + 5; const LL mod = 1e9 + 7; const double eps = 1e-11; const double pi = acos(-1); const int INF = 0x3f3f3f3f; const LL lINF = 0x3f3f3f3f3f3f3f3f; const int maxn = 2e5 + 10; const int N = 32; int level[M];//顶点到源点的距离标号 int iter[M];//当前弧 int t; int n, m; struct edge { int to; LL cap, rev; edge(int t, LL c, LL r) :to(t), cap(c), rev(r) {} }; struct Edge { int v; LL w; Edge() {} Edge(int a, LL b) { v = a; w = b; } }; vector<Edge> edge1[M]; vector<edge> g[M]; void init(int n) { for (int i = 1; i <= n; i++) { g[i].clear(); edge1[i].clear(); } memset(level, -1, sizeof(level)); memset(iter, 0, sizeof(iter)); } void addedge(int from, int to, LL cap) { g[from].push_back(edge(to, cap, g[to].size())); g[to].push_back(edge(from, 0, g[from].size() - 1)); } void bfs(int s) { memset(level, -1, sizeof(level)); queue<int>que; level[s] = 0; que.push(s); while (!que.empty()) { int v = que.front(); que.pop(); for (int i = 0; i < g[v].size(); i++) { edge &e = g[v][i]; if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; que.push(e.to); } } } } LL dfs(int v, int t, LL f) { if (v == t) return f; for (int &i = iter[v]; i < g[v].size(); i++) { edge &e = g[v][i]; if (e.cap > 0 && level[v] < level[e.to]) { LL d = dfs(e.to, t, min(f, e.cap)); if (d > 0) { e.cap -= d; g[e.to][e.rev].cap += d; return d; } } } return 0; } LL maxflow(int s, int t) { LL flow = 0; while (1) { bfs(s); if (level[t] < 0) return flow; memset(iter, 0, sizeof(iter)); LL f; while ((f = dfs(s, t, INF)) > 0) { flow += f; } } } int isv[M]; LL d[M]; int tot; struct node { int u; LL dis; node() {} node(int a, LL b) { u = a; dis = b; } bool operator <(const node & a)const { if (dis == a.dis) return u < a.u; else return dis > a.dis; } }; struct edge2 { int u, v; LL cost; }ed2[M*2]; void dikjstra(int s) { for (int i = 0; i <= n; i++) { d[i] = lINF; isv[i] = 0; } d[s] = 0; priority_queue<node>que; que.push(node(s, d[s])); while (!que.empty()) { node nw = que.top(); que.pop(); int u = nw.u; isv[u] = 1; for (int i = 0; i < edge1[u].size(); i++) { int v = edge1[u][i].v; LL w = edge1[u][i].w; if (isv[v]) continue; if (d[v] > d[u] + w) { d[v] = d[u] + w; que.push(node(v, d[v])); } } } } void addedge1(int a, int b, LL c) { edge1[a].push_back(Edge(b, c)); } void addedge2(int u, int v, LL cost) { ed2[tot].u = u; ed2[tot].v = v; ed2[tot++].cost = cost; } int main() { ios::sync_with_stdio(false); cin >> t; while (t--) { cin >> n >> m; init(n); tot = 0; for (int i = 0; i < m; i++) { int u, v; LL cost; cin >> u >> v >> cost; addedge1(u, v, cost); addedge2(u, v, cost); } if (n == 1) { cout << 0 << endl; continue; } dikjstra(1); for (int i = 0; i < m; i++) { if (d[ed2[i].u] + ed2[i].cost == d[ed2[i].v]) { addedge(ed2[i].u, ed2[i].v, ed2[i].cost); } } cout << maxflow(1, n) << endl; } }