[2019杭电多校第一场][hdu6582]Path(最短路&&最小割)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582
题意:删掉边使得1到n的最短路改变,删掉边的代价为该边的边权。求最小代价。
比赛时一片浆糊,赛后听到dinic瞬间思维通透XD
大致做法就是先跑一遍最短路,然后再保留所有满足dis[i]+w==dis[j]的边,在这些边上跑最小割(dinic)。
代码写的异常丑陋,见谅QAQ
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstring> 6 #include<string> 7 #include<queue> 8 using namespace std; 9 typedef long long ll; 10 const ll maxn = 3e5 + 10; 11 const ll inf = 1e18; 12 struct node { 13 ll s, e, next; 14 ll w; 15 }edge[maxn * 2], edge2[maxn * 2]; 16 ll head[maxn], head2[maxn], len, len2; 17 void init() { 18 memset(head, -1, sizeof(head)); 19 memset(head2, -1, sizeof(head2)); 20 len = len2 = 0; 21 } 22 void add(ll s, ll e, ll w) { 23 edge[len].s = s; 24 edge[len].e = e; 25 edge[len].w = w; 26 edge[len].next = head[s]; 27 head[s] = len++; 28 } 29 void add2(ll s, ll e, ll w) { 30 edge2[len2].s = s; 31 edge2[len2].e = e; 32 edge2[len2].w = w; 33 edge2[len2].next = head2[s]; 34 head2[s] = len2++; 35 } 36 struct p { 37 ll dis, num; 38 bool operator<(const p&a)const { 39 return a.dis < dis; 40 } 41 }; 42 ll dis[maxn]; 43 ll vis[maxn]; 44 void dij(ll n) { 45 priority_queue<p>q; 46 for (ll i = 1; i <= n; i++) 47 dis[i] = inf, vis[i] = 0; 48 q.push({ 0ll,1ll }); 49 dis[1] = 0ll; 50 while (!q.empty()) { 51 ll x = q.top().num; 52 q.pop(); 53 if (vis[x]) 54 continue; 55 vis[x] = 1; 56 for (ll i = head[x]; i != -1; i = edge[i].next) { 57 ll y = edge[i].e; 58 if (dis[y] > dis[x] + edge[i].w) { 59 dis[y] = dis[x] + edge[i].w; 60 q.push({ dis[y],y }); 61 } 62 } 63 } 64 } 65 ll d[maxn]; 66 bool bfs(ll s, ll t) { 67 queue<ll>q; 68 memset(d, 0, sizeof(d)); 69 d[s] = 1ll; 70 q.push(s); 71 while (!q.empty()) { 72 ll x = q.front(); q.pop(); 73 for (ll i = head2[x]; i != -1; i = edge2[i].next) { 74 ll y = edge2[i].e; 75 if (edge2[i].w && !d[y]) { 76 d[y] = d[x] + 1ll; 77 q.push(y); 78 } 79 } 80 } 81 return d[t]; 82 } 83 ll dfs(ll x, ll t, ll limit) { 84 if (x == t) 85 return limit; 86 ll add, ans = 0; 87 for (ll i = head2[x]; i != -1; i = edge2[i].next) { 88 ll y = edge2[i].e; 89 if (d[y] == d[x] + 1 && edge2[i].w) { 90 add = dfs(y, t, min(limit, edge2[i].w)); 91 edge2[i].w -= add; 92 edge2[i ^ 1].w += add; 93 ans += add; 94 limit -= add; 95 if (!limit) 96 break; 97 } 98 } 99 if (!ans) 100 d[x] = -1; 101 return ans; 102 } 103 ll dinic(ll s, ll t) { 104 ll ans = 0; 105 while (bfs(s, t)) 106 ans += dfs(s, t, inf); 107 return ans; 108 } 109 int main() { 110 ll t; 111 scanf("%lld", &t); 112 while (t--) { 113 ll n, m; 114 init(); 115 scanf("%lld%lld", &n, &m); 116 ll x, y, z; 117 for (ll i = 1; i <= m; i++) { 118 scanf("%lld%lld%lld", &x, &y, &z); 119 add(x, y, z); 120 } 121 dij(n); 122 for (ll i = 1; i <= n; i++) 123 for (ll j = head[i]; j != -1; j = edge[j].next) 124 if (dis[edge[j].s] + edge[j].w == dis[edge[j].e]) 125 add2(edge[j].s, edge[j].e, edge[j].w), add2(edge[j].e, edge[j].s, 0ll); 126 printf("%lld\n", dinic(1, n)); 127 } 128 return 0; 129 }