hdu 6852Path6(最短路+最小割)
Posted mmminoz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6852Path6(最短路+最小割)相关的知识,希望对你有一定的参考价值。
•题意
有n个城市,标号1-n
现花费最小的代价堵路
使得从1号城市到n号城市的路径边长
(注意只是变长不是最长)
堵一条路的代价是这条路的权值
•思路
在堵路以前,从1到n的最小路径当然是最短路
想要路径边长就要在最短路上动手脚
把从1到n的最短路找出来形成一个最短路图,
然后用最小的代价使得最短路图不连通
也就是求这个最短路图的最小割
那怎么建这个最短路图呢?
分别以1和n为源点跑一遍dijkstra,找出每个点到1和n的最短路
设$dis[1][i]$为1到i的最短路,$dis[n][i]$为i到n的最短路
$1->u->v->n$是$1->n$的一条最短路即$dis[1][u]+w[u->v]+dis[n][v]=dis[1][n]$
那么,u->v是1->n最短路上的一条边,加入最短路图中
(由于代码被某人嫌弃太乱,所以对dijkstra和dinic封装了一下...)
•代码
(未封装版)
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mem(a,b) memset(a,b,sizeof(a)) 4 #define ll long long 5 #define INF 0x3f3f3f3f3f3f3f3f 6 #define P pair<long long,int> 7 const int maxn=1e5+5; 8 int n,m; 9 struct Edge 10 { 11 int v; 12 ll w; 13 int next; 14 }de[maxn],fe[maxn],e[maxn]; 15 16 int head1[maxn],head2[maxn]; 17 int cnt1,cnt2; 18 void add(int u,int v,ll w) 19 { 20 de[++cnt1]={v,w,head1[u]}; 21 head1[u]=cnt1; 22 23 fe[++cnt2]={u,w,head2[v]}; 24 head2[v]=cnt2; 25 } 26 27 ll dis1[maxn],disn[maxn]; 28 bool vis1[maxn],visn[maxn]; 29 priority_queue<P,vector<P>,greater<P> >pq; 30 31 void dijkstra() 32 { 33 while(!pq.empty()) 34 pq.pop(); 35 for(int i=1;i<=n;i++) 36 dis1[i]=INF,vis1[i]=0; 37 dis1[1]=0; 38 pq.push(make_pair(0,1)); 39 while(!pq.empty()) 40 { 41 int u=pq.top().second; 42 pq.pop(); 43 if(!vis1[u]) 44 { 45 vis1[u]=1; 46 for(int i=head1[u];~i;i=de[i].next) 47 { 48 int v=de[i].v; 49 dis1[v]=min(dis1[v],dis1[u]+de[i].w); 50 pq.push(make_pair(dis1[v],v)); 51 } 52 } 53 } 54 55 while(!pq.empty()) 56 pq.pop(); 57 for(int i=1;i<=n;i++) 58 disn[i]=INF,visn[i]=0; 59 disn[n]=0; 60 61 pq.push(make_pair(0,n)); 62 while(!pq.empty()) 63 { 64 int u=pq.top().second; 65 pq.pop(); 66 if(!visn[u]) 67 { 68 visn[u]=1; 69 for(int i=head2[u];~i;i=fe[i].next) 70 { 71 int v=fe[i].v; 72 disn[v]=min(disn[v],disn[u]+fe[i].w); 73 pq.push(make_pair(disn[v],v)); 74 } 75 } 76 } 77 } 78 79 int head[maxn],cnt; 80 int cur[maxn],d[maxn]; 81 void addEdge(int u,int v,ll w) 82 { 83 e[++cnt]={v,w,head[u]}; 84 head[u]=cnt; 85 86 e[++cnt]={u,0,head[v]}; 87 head[v]=cnt; 88 } 89 90 bool bfs() 91 { 92 queue<int> q; 93 for(int i=1;i<=n;i++) 94 d[i]=-1; 95 d[1]=0; 96 q.push(1); 97 while(!q.empty()) 98 { 99 int u=q.front(); 100 q.pop(); 101 for(int i=head[u];~i;i=e[i].next) 102 { 103 int v=e[i].v; 104 if(d[v]==-1&&e[i].w>0) 105 { 106 d[v]=d[u]+1; 107 q.push(v); 108 } 109 } 110 } 111 return d[n]!=-1; 112 } 113 114 ll dfs(int u,ll flow) 115 { 116 ll nowflow=0; 117 if(u==n) return flow; 118 for(int i=cur[u];~i;i=e[i].next) 119 { 120 cur[u]=i; 121 int v=e[i].v; 122 if(d[v]==d[u]+1&&e[i].w>0) 123 { 124 ll k=dfs(v,min(flow-nowflow,e[i].w)); 125 if(k) 126 { 127 nowflow+=k; 128 e[i].w-=k; 129 e[i^1].w+=k; 130 if(nowflow==flow) 131 break; 132 } 133 } 134 } 135 if(!nowflow) d[u]=-2; 136 return nowflow; 137 } 138 139 ll Dinic() 140 { 141 ll ans=0; 142 while(bfs()) 143 { 144 for(int i=1;i<=n;i++) 145 cur[i]=head[i]; 146 147 ans+=dfs(1,INF); 148 } 149 return ans; 150 } 151 152 153 154 void Init() 155 { 156 mem(head1,-1); 157 mem(head2,-1); 158 mem(head,-1); 159 cnt1=cnt2=cnt=-1; 160 } 161 162 int main() 163 { 164 // freopen("C:\Users\14685\Desktop\C++workspace\in&out\contest","r",stdin); 165 int T; 166 scanf("%d",&T); 167 while(T--) 168 { 169 scanf("%d%d",&n,&m); 170 Init(); 171 for(int i=1;i<=m;i++) 172 { 173 int u,v; 174 ll w; 175 scanf("%d%d%lld",&u,&v,&w); 176 add(u,v,w); 177 } 178 179 dijkstra(); 180 181 for(int u=1;u<=n;u++) 182 { 183 for(int i=head1[u];~i;i=de[i].next) 184 { 185 int v=de[i].v; 186 if(dis1[u]+disn[v]+de[i].w==dis1[n]) 187 { 188 // printf("***%d %d %d ",u,v,de[i].w); 189 addEdge(u,v,de[i].w); 190 } 191 } 192 } 193 194 printf("%lld ",Dinic()); 195 } 196 }
(封装版)
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pli pair<ll,int> 5 #define INF 0x3f3f3f3f3f3f3f3f 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 const int maxn=1e5+5; 8 int n,m; 9 struct Edge 10 { 11 int v; 12 ll w; 13 int next; 14 }G[maxn<<1],e[maxn<<1]; 15 int dhead[maxn],dcnt; 16 void addEdge(int u,int v,ll w) 17 { 18 G[++dcnt]={v,w,dhead[u]}; 19 dhead[u]=dcnt; 20 } 21 22 struct Dij 23 { 24 ll dis[2][maxn]; 25 bool vis[maxn]; 26 priority_queue<pli,vector<pli>,greater<pli> > q; 27 void dij(int s,int n,bool ok) 28 { 29 for(int i=1;i<=n;i++) 30 dis[ok][i]=INF,vis[i]=0; 31 dis[ok][s]=0; 32 q.push({0,s}); 33 while(!q.empty()) 34 { 35 int u=q.top().second; 36 q.pop(); 37 if(vis[u]) 38 continue; 39 vis[u]=1; 40 for(int i=dhead[u];~i;i=G[i].next) 41 { 42 ///偶数是正向边,ok=true是正向边 43 if(ok && i&1) 44 continue; 45 ///奇数是反向边,ok=false是反向边 46 if(!ok && !(i&1)) 47 continue; 48 49 int v=G[i].v; 50 ll w=G[i].w; 51 if(dis[ok][v]>dis[ok][u]+w) 52 { 53 dis[ok][v]=dis[ok][u]+w; 54 if(!vis[v]) 55 q.push({dis[ok][v],v}); 56 } 57 } 58 } 59 } 60 }dij1,dijn; 61 62 int head[maxn],cnt; 63 void add(int u,int v,ll w) 64 { 65 e[++cnt]={v,w,head[u]}; 66 head[u]=cnt; 67 } 68 struct Dinic 69 { 70 int cur[maxn],d[maxn]; 71 int s=1,t=n; 72 bool bfs() 73 { 74 queue<int> q; 75 for(int i=1;i<=n;i++) 76 d[i]=-1; 77 d[1]=0; 78 q.push(1); 79 while(!q.empty()) 80 { 81 int u=q.front(); 82 q.pop(); 83 for(int i=head[u];~i;i=e[i].next) 84 { 85 int v=e[i].v; 86 if(d[v]==-1&&e[i].w>0) 87 { 88 d[v]=d[u]+1; 89 q.push(v); 90 } 91 } 92 } 93 return d[n]!=-1; 94 } 95 96 ll dfs(int u,ll flow) 97 { 98 ll nowflow=0; 99 if(u==n) return flow; 100 for(int i=cur[u];~i;i=e[i].next) 101 { 102 cur[u]=i; 103 int v=e[i].v; 104 if(d[v]==d[u]+1&&e[i].w>0) 105 { 106 ll k=dfs(v,min(flow-nowflow,e[i].w)); 107 if(k) 108 { 109 nowflow+=k; 110 e[i].w-=k; 111 e[i^1].w+=k; 112 if(nowflow==flow) 113 break; 114 } 115 } 116 } 117 if(!nowflow) d[u]=-2; 118 return nowflow; 119 } 120 121 ll din() 122 { 123 ll ans=0; 124 while(bfs()) 125 { 126 for(int i=1;i<=n;i++) 127 cur[i]=head[i]; 128 129 ans+=dfs(1,INF); 130 } 131 return ans; 132 } 133 }_din; 134 135 void Init() 136 { 137 mem(dhead,-1); 138 dcnt=-1; 139 mem(head,-1); 140 cnt=-1; 141 } 142 143 int main() 144 { 145 int T; 146 scanf("%d",&T); 147 while(T--) 148 { 149 Init(); 150 scanf("%d%d",&n,&m); 151 for(int i=1;i<=m;i++) 152 { 153 int u,v; 154 ll w; 155 scanf("%d%d%lld",&u,&v,&w); 156 ///跑1到其他点的最短路 加正向边 157 addEdge(u,v,w); 158 ///跑n到其他点的最短路 加反向边 159 addEdge(v,u,w); 160 } 161 162 dij1.dij(1,n,true); 163 dijn.dij(n,n,false); 164 165 166 for(int u=1;u<=n;u++) 167 { 168 for(int i=dhead[u];~i;i=G[i].next) 169 { 170 int v=G[i].v; 171 ll w=G[i].w; 172 if(dij1.dis[1][u]+dijn.dis[0][v]+w==dij1.dis[1][n]) 173 { 174 add(u,v,w); 175 add(v,u,0); 176 } 177 } 178 } 179 printf("%lld ",_din.din()); 180 } 181 }
以上是关于hdu 6852Path6(最短路+最小割)的主要内容,如果未能解决你的问题,请参考以下文章