kZjPBD.jpg

[ACM-ICPC 2018 沈阳网络赛] F. Fantastic Graph (有源汇上下界可行流+建图)

"Oh, There is a bipartite graph.""Make it Fantastic."

X wants to check whether a bipartite graph is a fantastic graph. He has two fantastic numbers, and he wants to let all the degrees to between the two boundaries. You can pick up several edges from the current graph and try to make the degrees of every point to between the two boundaries. If you pick one edge, the degrees of two end points will both increase by one. Can you help X to check whether it is possible to fix the graph?

Input

There are at most 3030 test cases.

For each test case,The first line contains three integers NN the number of left part graph vertices, MM the number of right part graph vertices, and KK the number of edges ( 1 \le N \le 20001N2000,0 \le M \le 20000M2000,0 \le K \le 60000K6000 ). Vertices are numbered from 11 to NN.

The second line contains two numbers L, RL,(0 \le L \le R \le 300)(0LR300). The two fantastic numbers.

Then KK lines follows, each line containing two numbers UU, V(1 \le U \le N,1 \le V \le M)(1UN,1VM). It shows that there is a directed edge from UU-th spot to VV-th spot.

Note. There may be multiple edges between two vertices.

Output

One line containing a sentence. Begin with the case number. If it is possible to pick some edges to make the graph fantastic, output "Yes" (without quote), else output "No" (without quote).

样例输入

3 3 7
2 3
1 2
2 3
1 3
3 2
3 3
2 1
2 1
3 3 7
3 4
1 2
2 3
1 3
3 2
3 3
2 1
2 1

样例输出

Case 1: Yes
Case 2: No


SOLUTION:
 开一个源点s和一个汇点t,对于每个N点,从s连一条[L,R]的边,
对于每一个M点,连向t一条[L,R]的边,
对于图中原本的NM之间的边,连一条[0,1]的边,然后跑有源汇点有上下界的网络流就可以。

CODE:
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <queue>
  6 
  7 using namespace std;
  8 const int INF=2147000000;
  9 const int maxn=4000+100;
 10 const int maxm=100000+100;
 11 struct Dinic
 12 {
 13     int n,m,s,t,sz;
 14     int head[maxn],Next[maxm*2],to[maxm*2],cap[2*maxm],flow[2*maxm];
 15     int vis[maxn],d[maxn],cur[maxn];
 16     void init(int n)
 17     {
 18         this->n=n;
 19         sz=-1;
 20         memset(head,-1,sizeof(head));
 21     }
 22     void add_edge(int a,int b,int c)
 23     {
 24         ++sz;
 25         to[sz]=b;
 26         cap[sz]=c;
 27         flow[sz]=c;
 28         Next[sz]=head[a];
 29         head[a]=sz;
 30         ++sz;
 31         to[sz]=a;
 32         cap[sz]=c;
 33         flow[sz]=0;
 34         Next[sz]=head[b];
 35         head[b]=sz;
 36     }
 37     bool BFS()
 38     {
 39         memset(vis,0,sizeof(vis));
 40         queue<int>q;
 41         vis[s]=1;
 42         q.push(s);
 43         d[s]=0;
 44         while(!q.empty())
 45         {
 46             int u=q.front();
 47             q.pop();
 48             for(int i=head[u]; i!=-1; i=Next[i])
 49             {
 50                 int v=to[i];
 51                 if(!vis[v]&&flow[i])
 52                 {
 53                     vis[v]=1;
 54                     d[v]=d[u]+1;
 55                     q.push(v);
 56                 }
 57             }
 58         }
 59         return vis[t];
 60     }
 61     int DFS(int x,int a)
 62     {
 63         if(x==t||a==0)
 64             return a;
 65         int Flow=0,f;
 66         for(int &i=cur[x]; i!=-1; i=Next[i])
 67         {
 68             int v=to[i];
 69             if(d[v]==d[x]+1&&(f=DFS(v,min(a,flow[i])))>0)
 70             {
 71                 Flow+=f;
 72                 flow[i]-=f;
 73                 flow[i^1]+=f;
 74                 a-=f;
 75                 if(a==0)
 76                     break;
 77             }
 78         }
 79         return Flow;
 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             for(int i=0; i<=n; i++)
 88                 cur[i]=head[i];
 89            // Flow+=DFS(s,INF);
 90             int d;
 91             while(d=DFS(s,INF))Flow+=d;
 92 
 93         }
 94         //printf("!!%d\n",Flow);
 95         return Flow;
 96     }
 97 } dinic;
 98 int N,M,K,L,R,sum,kase;
 99 int du[maxn];
100 int main()
101 {
102     kase=0;
103     while(scanf("%d%d%d",&N,&M,&K)!=EOF)
104     {
105         ++kase;
106         memset(du,0,sizeof(du));
107         scanf("%d%d",&L,&R);
108         dinic.init(N+M+4);
109         for(int i=1; i<=N; i++)
110         {
111             dinic.add_edge(0,i,R-L);
112             du[i]+=L;
113             du[0]-=L;
114         }
115         sum=0;
116         for(int i=1; i<=M; i++)
117         {
118             dinic.add_edge(i+N,N+M+1,R-L);
119             du[i+N]-=L;
120             du[N+M+1]+=L;
121         }
122         int a,b;
123         for(int i=1; i<=K; i++)
124         {
125             scanf("%d%d",&a,&b);
126             dinic.add_edge(a,b+N,1);
127         }
128         dinic.add_edge(N+M+1,0,INF);
129         int s=N+M+2,t=N+M+3;
130         for(int i=0; i<=N+M+1; i++)
131         {
132             if(du[i]>0)
133             {
134                 sum+=du[i];
135                 dinic.add_edge(s,i,du[i]);
136             }
137             if(du[i]<0)
138             {
139                 dinic.add_edge(i,t,-du[i]);
140             }
141         }
142         int maxflow=dinic.Maxflow(s,t);
143         //  printf("%d %d\n",maxflow,sum);
144         printf("Case %d: ",kase);
145         if(maxflow==sum)
146         {
147             printf("Yes\n");
148         }
149         else
150         {
151             printf("No\n");
152         }
153     }
154     return 0;
155 }

 










posted @ 2019-07-12 16:38  Through_The_Night  阅读(180)  评论(0编辑  收藏  举报