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封装了一下...)

•代码

(未封装版)

技术图片
  1 #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 Code

 

(封装版)

技术图片
  1 #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 }
View Code

 

以上是关于hdu 6852Path6(最短路+最小割)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5889 Barricade最小割

hdu 5889 Barricade最小割

hdu 5294 Tricks Device 最短路建图+最小割

HDU 5889 Barricade(最短路+最小割)

HDU - 3035 War(对偶图求最小割+最短路)

hdu 3870 最小割转化为最短路径2