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 }