码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-02-09 12:07:44      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:scanf   contest   turn   一个   链接   queue   ++   add   algo   

题目链接: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("\n");
169     }
170     return 0;
171 }

 

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

标签:scanf   contest   turn   一个   链接   queue   ++   add   algo   

原文地址:https://www.cnblogs.com/letlifestop/p/10357210.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!