2018沈阳网赛F--上下界网络流

建图:

首先加一个源点s和汇点t,分别连接在二分图的左边和右边,每条弧的上下界为【L, R】,二分图左边和右边之间连弧上下界为【0,1】,其实就相当于连弧为1。

然后问题就转换为:有源汇最大流。

继续建图:

建立弧<t,s><,容量下界为00,上界为∞。

加一个超级源ss和超级汇tt

 

对于所有有上下界的弧(也就是s,t分别连接左边和右边的弧)进行分边

一条为<ss,v>,容量为L

一条为<u,tt>>,容量为L

一条为<u,v>,容量为R-L

其中前两条弧一般称为附加弧。

 

然后跑一遍最大流,如果ss所有的出边(或者是TT所有的入边)都满流,就输出Yes

 

以后再加图说明吧....

(代码说明一下..   0为超级源,NV为超级汇,  NV-2为源, NV-1为汇)

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <queue>
  7 using namespace std;
  8 const int N = 5005;
  9 const int inf = 0x3f3f3f;
 10 
 11 struct Edge
 12 {
 13     int from,to,cap,flow;
 14     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
 15 };
 16 
 17 struct Din
 18 {
 19     int s,t;
 20     vector<Edge>edges;
 21     vector<int>G[N];
 22     bool vis[N];
 23     int d[N];
 24     int cur[N];
 25 
 26     void addedge(int from,int to,int cap)
 27     {
 28         edges.push_back(Edge(from,to,cap,0));
 29         edges.push_back(Edge(to,from,0,0));
 30         int  m=edges.size();
 31         G[from].push_back(m-2);
 32         G[to].push_back(m-1);
 33     }
 34 
 35     bool bfs()
 36     {
 37         memset(vis,0,sizeof(vis));
 38         queue<int>Q;
 39         Q.push(s);
 40         d[s]=0;
 41         vis[s]=1;
 42         while(!Q.empty())
 43         {
 44             int x=Q.front();
 45             Q.pop();
 46             for(int i=0; i<G[x].size(); i++)
 47             {
 48                 Edge&e=edges[G[x][i]];
 49                 if(!vis[e.to]&&e.cap>e.flow)
 50                 {
 51                     vis[e.to]=1;
 52                     d[e.to]=d[x]+1;
 53                     Q.push(e.to);
 54                 }
 55             }
 56         }
 57         return vis[t];
 58     }
 59 
 60     int dfs(int x,int a)
 61     {
 62         if(x==t||a==0)
 63             return a;
 64         int flow=0,f;
 65         for(int i=cur[x]; i<G[x].size(); i++)
 66         {
 67             Edge&e=edges[G[x][i]];
 68             if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
 69             {
 70                 e.flow += f;
 71                 edges[G[x][i]^1].flow -= f;
 72                 flow += f;
 73                 a -= f;
 74                 if(!a)
 75                     break;
 76             }
 77         }
 78         return flow;
 79     }
 80 
 81     int Maxflow(int s,int t)
 82     {
 83         this->s=s,this->t=t;
 84         int flow=0;
 85         while(bfs())
 86         {
 87             memset(cur,0,sizeof(cur));
 88             flow += dfs(s,inf);
 89         }
 90         return flow;
 91     }
 92 };
 93 
 94 int main()
 95 {
 96     int N,F,D;
 97     int cnt = 0;
 98     while(scanf("%d%d%d",&N,&F,&D) != EOF)
 99     {
100         Din tmp;
101         int flag = 1;
102         int NV = N+F+2+1, NE=0;
103         int a, b;
104         int l, r;
105         scanf("%d%d",&l, &r);
106         for(int i=0; i<D; i++)
107         {
108             scanf("%d%d",&a, &b);
109             tmp.addedge(a,N+b, 1);
110         }
111         for(int i=1; i<=N; i++)
112         {
113             tmp.addedge(NV-2,i, r-l);
114             tmp.addedge(0,i, l);
115             tmp.addedge(NV-2,NV, l);
116         }
117         for(int i=1; i<=F; i++)
118         {
119             tmp.addedge(N+i,NV-1, r-l);
120             tmp.addedge(0,NV-1, l);
121             tmp.addedge(N+i,NV, l);
122         }
123         tmp.addedge(NV-1,NV-2, inf);
124         int tt = tmp.Maxflow(NE,NV);
125         for(int i=0; i<tmp.G[0].size(); i++)
126         {
127             Edge &e=tmp.edges[tmp.G[0][i]];
128             if(e.flow < l){
129                 flag = 0;
130                 break;
131             }
132         }
133         cnt++;
134         if(flag)
135             printf("Case %d: Yes\n", cnt);
136         else
137             printf("Case %d: No\n", cnt);
138     }
139 }
View Code

 

posted @ 2018-09-08 18:49  feifei97  阅读(347)  评论(0编辑  收藏  举报