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

 

posted @ 2019-07-25 16:00  祈梦生  阅读(487)  评论(0编辑  收藏  举报