B - Internship (网络流关键割边)

Posted letlifestop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B - Internship (网络流关键割边)相关的知识,希望对你有一定的参考价值。

题目链接:https://cn.vjudge.net/contest/281961#problem/B

题目大意:给你n个城市,中间有一些中转站,然后给你终点,再给你l条轨道以及流量,问你增加哪几条轨道的流量可以使得流到终点的流量增加。

具体思路:首先分析一波,一开始想的是找割边,但是只是找出割边是不可以的。举个例子 : s->u->t,这样的话,假设这两条边都是满流,都可以当做割边,但是如果只是增加割边的流量的话,会受到其他边的流量的限制,最终流量还是不会增加的,所以,换一个思路,我们先跑一遍最大流,然后观察残余网络的情况,如果一条边的起点和终点对应的起点作为另一条边的终点以及终点对应另一条边的起点的话,依旧是如果增加当前这条边的流量的话,还是可以增加流量的,这样关键割边就找出来了。

AC代码:

  1 #include<iostream>
  2 #include<stack>
  3 #include<queue>
  4 #include<iomanip>
  5 #include<stdio.h>
  6 #include<cstring>
  7 #include<cstring>
  8 #include<cmath>
  9 #include<algorithm>
 10 #include<map>
 11 #include<vector>
 12 using namespace std;
 13 # define ll long long
 14 const int maxn = 4e3+100;
 15 # define inf 0x3f3f3f3f
 16 int st,ed;
 17 int prev[maxn];
 18 int head[maxn];
 19 int line[maxn];
 20 int vis1[maxn],vis2[maxn];
 21 struct node
 22 {
 23     int fr;
 24     int to;
 25     int flow;
 26     int nex;
 27 } edge[maxn];
 28 int num;
 29 void init()
 30 {
 31     memset(head,-1,sizeof(head));
 32     memset(vis1,0,sizeof(vis1));
 33     memset(vis2,0,sizeof(vis2));
 34     num=0;
 35 }
 36 void addedge(int fr,int to,int flow)
 37 {
 38     edge[num].to=to;
 39     edge[num].fr=fr;
 40     edge[num].flow=flow;
 41     edge[num].nex=head[fr];
 42     head[fr]=num++;
 43     edge[num].to=fr;
 44     edge[num].fr=to;
 45     edge[num].flow=0;
 46     edge[num].nex=head[to];
 47     head[to]=num++;
 48 }
 49 bool bfs()
 50 {
 51     memset(prev,-1,sizeof(prev));
 52     prev[st]=1;
 53     queue<int>q;
 54     q.push(st);
 55     while(!q.empty())
 56     {
 57         int top=q.front();
 58         q.pop();
 59         for(int i=head[top]; i!=-1; i=edge[i].nex)
 60         {
 61             int temp=edge[i].to;
 62             if(prev[temp]==-1&&edge[i].flow>0)
 63             {
 64                 prev[temp]=prev[top]+1;
 65                 q.push(temp);
 66             }
 67         }
 68     }
 69     return prev[ed]!=-1;
 70 }
 71 int dfs(int u,int flow)
 72 {
 73     if(u==ed)
 74         return flow;
 75     int res=0;
 76     for(int i=head[u]; i!=-1; i=edge[i].nex)
 77     {
 78         int t=edge[i].to;
 79         if(prev[t]==(prev[u]+1)&&edge[i].flow>0)
 80         {
 81             int temp=dfs(t,min(flow,edge[i].flow));
 82             edge[i].flow-=temp;
 83             edge[i^1].flow+=temp;
 84             res+=temp;
 85             flow-=temp;
 86             if(flow==0)
 87                 break;
 88         }
 89     }
 90     if(res==0)
 91         prev[u]=-1;
 92     return res;
 93 }
 94 void  dinic()
 95 {
 96     int ans=0;
 97     while(bfs())
 98     {
 99         ans+=dfs(st,inf);
100     }
101 }
102 void dfs1(int u)
103 {
104     vis1[u]=1;
105     for(int i=head[u]; i!=-1; i=edge[i].nex)
106     {
107         int v=edge[i].to;
108         if(!vis1[v]&&edge[i].flow)
109             dfs1(v);
110     }
111 }
112 void dfs2(int u)
113 {
114     vis2[u]=1;
115     for(int i=head[u]; i!=-1; i=edge[i].nex)
116     {
117         int v=edge[i].to;
118         if(!vis2[v]&&edge[i^1].flow)
119         {
120             dfs2(v);
121         }
122     }
123 }
124 int main()
125 {
126     int n,m,l;
127     while(~scanf("%d",&n))
128     {
129         if(n==0)
130             break;
131         init();
132         scanf("%d %d",&m,&l);
133         st=n+m+1;
134         ed=0;
135         int t1,t2,t3;
136         for(int i=0; i<l; i++)
137         {
138             scanf("%d %d %d",&t1,&t2,&t3);
139             line[i]=num;
140             addedge(t1,t2,t3);
141         }
142         for(int i=1; i<=n; i++)
143         {
144             addedge(st,i,inf);
145         }
146         dinic();
147         dfs1(st);
148         dfs2(ed);
149        // cout<<1<<endl;
150         int flag=1;
151         for(int i=0; i<l; i++)
152         {
153       //  cout<<i<<endl;
154             if(edge[line[i]].flow==0&&vis1[edge[line[i]].fr]&&vis2[edge[line[i]].to])
155             {
156            //     cout<<i<<endl;
157                 if(flag)
158                 {
159                     printf("%d",i+1);
160                     flag=0;
161                 }
162                 else
163                 {
164                     printf(" %d",i+1);
165                 }
166             }
167         }
168         printf("
");
169     }
170     return 0;
171 }

 

以上是关于B - Internship (网络流关键割边)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6214 最小割边

2017青岛赛区网络赛 Smallest Minimum Cut 求最小割的最小割边数

Uva 10480 Sabotage 最大流

深谈网络流

[啊哈算法]关键道路(图的割边)

网络流+最小生成树的最少割边数--How Many to Be Happy?