HDU

题意:给定一个n个点m条边的有向图,每条边有个长度,可以花费等同于其长度的代价将其破坏掉,求最小的花费使得从1到n的最短路变长。

解法:先用dijkstra求出以1为源点的最短路,并建立最短路图(只保留d[v]=d[u]+e[i].c的边(u,v)),跑个最大流即可。

Dinic:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N=1e4+10,inf=0x3f3f3f3f3f3f3f3fll;
 5 ll n,m;
 6 struct MF {
 7     ll hd[N],ne,d[N],g[N],cur[N];
 8     struct E {ll v,cp,nxt;} e[N<<2];
 9     void init() {memset(hd,-1,sizeof hd),ne=0;}
10     void addedge(ll u,ll v,ll cp) {
11         e[ne]= {v,cp,hd[u]},hd[u]=ne++;
12         e[ne]= {u,0,hd[v]},hd[v]=ne++;
13     }
14     int bfs(ll s,ll t) {
15         queue<ll> q;
16         memset(d,-1,sizeof d);
17         d[s]=0,q.push(s);
18         while(q.size()) {
19             ll u=q.front();
20             q.pop();
21             for(ll i=hd[u]; ~i; i=e[i].nxt)if(e[i].cp) {
22                     ll v=e[i].v;
23                     if(!~d[v])d[v]=d[u]+1,q.push(v);
24                 }
25         }
26         return ~d[t];
27     }
28     ll dfs(ll t,ll u,ll f) {
29         if(u==t||!f)return f;
30         ll ret=0;
31         for(ll& i=cur[u]; ~i; i=e[i].nxt) {
32             ll v=e[i].v;
33             if(d[v]==d[u]+1) {
34                 ll df=dfs(t,v,min(f,e[i].cp));
35                 e[i].cp-=df,e[i^1].cp+=df,f-=df,ret+=df;
36                 if(!f)return ret;
37             }
38         }
39         return ret;
40     }
41     ll dinic(ll s,ll t) {
42         ll ret=0;
43         while(bfs(s,t)) {
44             for(ll i=1; i<=n; ++i)cur[i]=hd[i];
45             ret+=dfs(t,s,inf);
46         }
47         return ret;
48     }
49 } mf;
50 struct SP {
51     ll hd[N],ne,dp[N];
52     struct E {ll v,c,nxt;} e[N];
53     void init() {memset(hd,-1,sizeof hd),ne=0;}
54     void addedge(ll u,ll v,ll c) {e[ne]= {v,c,hd[u]},hd[u]=ne++;}
55     struct D {
56         ll u,g;
57         bool operator<(const D& b)const {return b.g>g;}
58     };
59     priority_queue<D> q;
60     void upd(ll u,ll ad) {if(dp[u]>ad)dp[u]=ad,q.push({u,ad});}
61     void dij(ll s) {
62         memset(dp,inf,sizeof dp);
63         upd(s,0);
64         while(q.size()) {
65             ll u=q.top().u,g=q.top().g;
66             q.pop();
67             if(dp[u]!=g)continue;
68             for(ll i=hd[u]; ~i; i=e[i].nxt) {
69                 ll v=e[i].v,c=e[i].c;
70                 upd(v,g+c);
71             }
72         }
73     }
74     void solve() {
75         dij(1);
76         for(ll u=1; u<=n; ++u) {
77             for(ll i=hd[u]; ~i; i=e[i].nxt) {
78                 ll v=e[i].v,c=e[i].c;
79                 if(dp[v]==dp[u]+c)mf.addedge(u,v,c);
80             }
81         }
82         printf("%lld
",mf.dinic(1,n));
83     }
84 } sp;
85 int main() {
86     ll T;
87     for(scanf("%lld",&T); T--;) {
88         sp.init(),mf.init();
89         scanf("%lld%lld",&n,&m);
90         while(m--) {
91             ll u,v,c;
92             scanf("%lld%lld%lld",&u,&v,&c);
93             sp.addedge(u,v,c);
94         }
95         sp.solve();
96     }
97     return 0;
98 }

ISAP:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N=1e4+10,inf=0x3f3f3f3f3f3f3f3fll;
 5 ll n,m;
 6 struct MF {
 7     ll hd[N],ne,d[N],g[N],cur[N];
 8     struct E {ll v,cp,nxt;} e[N<<2];
 9     void init() {memset(hd,-1,sizeof hd),ne=0;}
10     void addedge(ll u,ll v,ll cp) {
11         e[ne]= {v,cp,hd[u]},hd[u]=ne++;
12         e[ne]= {u,0,hd[v]},hd[v]=ne++;
13     }
14     void bfs(ll s) {
15         queue<ll> q;
16         memset(d,-1,sizeof d);
17         memset(g,0,sizeof g);
18         ++g[d[s]=0],q.push(s);
19         while(q.size()) {
20             ll u=q.front();
21             q.pop();
22             for(ll i=hd[u]; ~i; i=e[i].nxt) {
23                 ll v=e[i].v;
24                 if(!~d[v])++g[d[v]=d[u]+1],q.push(v);
25             }
26         }
27     }
28     ll dfs(ll s,ll t,ll u,ll f) {
29         if(u==t||!f)return f;
30         ll ret=0;
31         for(ll& i=cur[u]; ~i; i=e[i].nxt) {
32             ll v=e[i].v;
33             if(d[v]==d[u]-1) {
34                 ll df=dfs(s,t,v,min(f,e[i].cp));
35                 e[i].cp-=df,e[i^1].cp+=df,f-=df,ret+=df;
36                 if(!f)return ret;
37             }
38         }
39         if(!--g[d[u]])d[s]=n+1;
40         ++g[++d[u]],cur[u]=hd[u];
41         return ret;
42     }
43     ll isap(ll s,ll t) {
44         ll ret=0;
45         bfs(t);
46         for(ll i=1; i<=n; ++i)cur[i]=hd[i];
47         while(d[s]<n+1)ret+=dfs(s,t,s,inf);
48         return ret;
49     }
50 } mf;
51 struct SP {
52     ll hd[N],ne,dp[N];
53     struct E {ll v,c,nxt;} e[N];
54     void init() {memset(hd,-1,sizeof hd),ne=0;}
55     void addedge(ll u,ll v,ll c) {e[ne]= {v,c,hd[u]},hd[u]=ne++;}
56     struct D {
57         ll u,g;
58         bool operator<(const D& b)const {return b.g>g;}
59     };
60     priority_queue<D> q;
61     void upd(ll u,ll ad) {if(dp[u]>ad)dp[u]=ad,q.push({u,ad});}
62     void dij(ll s) {
63         memset(dp,inf,sizeof dp);
64         upd(s,0);
65         while(q.size()) {
66             ll u=q.top().u,g=q.top().g;
67             q.pop();
68             if(dp[u]!=g)continue;
69             for(ll i=hd[u]; ~i; i=e[i].nxt) {
70                 ll v=e[i].v,c=e[i].c;
71                 upd(v,g+c);
72             }
73         }
74     }
75     void solve() {
76         dij(1);
77         for(ll u=1; u<=n; ++u) {
78             for(ll i=hd[u]; ~i; i=e[i].nxt) {
79                 ll v=e[i].v,c=e[i].c;
80                 if(dp[v]==dp[u]+c)mf.addedge(u,v,c);
81             }
82         }
83         printf("%lld
",mf.isap(1,n));
84     }
85 } sp;
86 int main() {
87     ll T;
88     for(scanf("%lld",&T); T--;) {
89         sp.init(),mf.init();
90         scanf("%lld%lld",&n,&m);
91         while(m--) {
92             ll u,v,c;
93             scanf("%lld%lld%lld",&u,&v,&c);
94             sp.addedge(u,v,c);
95         }
96         sp.solve();
97     }
98     return 0;
99 }

这道题Dinic居然比ISAP快,我的代码ISAP跑了156ms,而Dinic只跑了93ms..

原文地址:https://www.cnblogs.com/asdfsag/p/11262488.html