【无源汇有上下界可行流】ACdream1211-Reactor Cooling

【题意】

给出一些边流量的上界和下界,问能否循环流通。

【思路】

黄学长讲得很清楚,直接贴过来:

上界用ci表示,下界用bi表示。

下界是必须流满的,那么对于每一条边,去掉下界后,其自由流为ci– bi。

主要思想:每一个点流进来的流=流出去的流

对于每一个点i,令

Mi= sum(i点所有流进来的下界流)– sum(i点所有流出去的下界流)

如果Mi大于0,代表此点必须还要流出去Mi的自由流,那么我们从源点连一条Mi的边到该点。

如果Mi小于0,代表此点必须还要流进来Mi的自由流,那么我们从该点连一条Mi的边到汇点。

如果求S->T的最大流,看是否满流(S的相邻边都流满)。

满流则有解,否则无解。

【错误点】

忘记清空vector和in数组了orz

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<queue>
  7 #define target n+1
  8 using namespace std;
  9 const int MAXM=100000+5;
 10 const int MAXN=200+5; 
 11 const int INF=0x7fffffff;
 12 struct node
 13 {
 14     int to,pos,cap;
 15 }; 
 16 vector<node> E[MAXM];
 17 int n,m,sum=0;
 18 int in[MAXN];
 19 int dist[MAXN];
 20 int low[MAXM];//记录下每条边的下界 
 21 int edge[MAXM][2];
 22 
 23 void addedge(int u,int v,int c)
 24 {
 25     E[u].push_back((node){v,E[v].size(),c});
 26     E[v].push_back((node){u,E[u].size()-1,0});
 27 }
 28 
 29 void init()
 30 {
 31     memset(in,0,sizeof(in));//不要忘记了要清空in 
 32     for (int i=0;i<target;i++) E[i].clear();//不要忘记了要清空vector 
 33     int u,v,c;
 34     for (int i=0;i<m;i++) 
 35     {
 36         scanf("%d%d%d%d",&u,&v,&low[i],&c);
 37         in[u]-=low[i];
 38         in[v]+=low[i];
 39         addedge(u,v,c-low[i]);
 40         edge[i][0]=v;
 41         edge[i][1]=E[v].size()-1;
 42     }
 43     sum=0;
 44     for (int i=1;i<=n;i++)
 45     {
 46         if (in[i]>0) 
 47         {
 48             addedge(0,i,in[i]);
 49             sum+=in[i];
 50         }
 51         else if (in[i]<0) addedge(i,target,-in[i]);
 52     }
 53 }
 54 
 55 int bfs()
 56 {
 57     memset(dist,-1,sizeof(dist));
 58     queue<int> que;
 59     while (!que.empty()) que.pop();
 60     que.push(0);
 61     dist[0]=0;
 62     
 63     while (!que.empty()) 
 64     {
 65         int head=que.front();
 66         que.pop();
 67         for (int i=0; i<E[head].size(); i++) 
 68         {
 69             node &tmp=E[head][i];
 70             if (dist[tmp.to]==-1 && tmp.cap>0)
 71             {    
 72                 dist[tmp.to]=dist[head]+1;
 73                 que.push(tmp.to);
 74                 if (tmp.to==target) return 1;
 75             }
 76         }
 77     }
 78     return 0;
 79 }
 80 
 81 int dfs(int s,int e,int maxflow)
 82 {
 83     int ret=0;
 84     if (s==e || maxflow==0) return maxflow;
 85     for (int i=0;i<E[s].size();i++)
 86     {
 87         node &tmp=E[s][i];
 88         if (dist[tmp.to]==dist[s]+1 && tmp.cap>0)
 89         {
 90             int delta=dfs(tmp.to,e,min(maxflow,tmp.cap));
 91             if (delta>0)
 92             {
 93                 ret+=delta;
 94                 tmp.cap-=delta;
 95                 E[tmp.to][tmp.pos].cap+=delta;
 96                 maxflow-=delta;
 97             }
 98         }
 99     }
100     return ret;
101 }
102 
103 void dinic()
104 {
105     int flow=0;
106     while (bfs())
107     {
108         int f=dfs(0,target,INF);
109         if (f>0)
110             flow+=f;
111         else break;
112     }
113     if (flow!=sum) cout<<"NO"<<endl;
114     else
115     {
116         cout<<"YES"<<endl; 
117         for (int i=0;i<m;i++) cout<<low[i]+E[edge[i][0]][edge[i][1]].cap<<endl;
118     }
119 }
120 
121 int main()
122 {
123     while (~(scanf("%d%d",&n,&m)))
124     {
125         init();
126         dinic(); 
127     }
128     return 0;
129 } 

 

你可能感兴趣的:(【无源汇有上下界可行流】ACdream1211-Reactor Cooling)