HDU - 6582 Path (最短路+最小割)
题意:给定一个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\n",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\n",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..