"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 30 test cases.
For each test case,The first line contains three integers N the number of left part graph vertices, M the number of right part graph vertices, and K the number of edges ( 1≤N≤2000,0≤M≤2000,0≤K≤6000). Vertices are numbered from 1 to N.
The second line contains two numbers L,R(0≤L≤R≤300). The two fantastic numbers.
Then K lines follows, each line containing two numbers U, V (1≤U≤N,1≤V≤M). It shows that there is a directed edge from U-th spot to V-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: Noc++
题意网络
一个二分图,左边N个点,右边M个点,中间K条边,问你是否能够删掉边使得全部点的度数在[L,R]之间测试
题解spa
比赛的时候写的网络流A的,赛后把本身hack了。。code
而后写了个贪心,发现仍是贪心好写(雾)blog
考虑两个集合A和B,A为L<=d[i]<=R,B为d[i]>Rthree
枚举每一个边ip
1.若是u和v都在B集合,直接删掉
2.若是u和v都在A集合,无所谓
3.若是u在B,v在A,而且v可删边即d[v]>L
4.若是u在A,v在B,而且u可删边即d[u]>Lstring
最后枚举N+M个点判断是否在[L,R]之间it
这个作法虽然不是官方作法,若是有hack的数据能够发评论
最后贴个官方作法,有源汇上下界网络流
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=6005; 5 6 int main() 7 { 8 int N,M,K,L,R,o=1,u[maxn],v[maxn],d[maxn]; 9 while(scanf("%d%d%d",&N,&M,&K)!=EOF) 10 { 11 memset(d,0,sizeof d); 12 scanf("%d%d",&L,&R); 13 int sum=0,flag=1; 14 for(int i=0;i<K;i++) 15 { 16 scanf("%d%d",&u[i],&v[i]);v[i]+=N; 17 d[u[i]]++,d[v[i]]++; 18 } 19 for(int i=0;i<K;i++) 20 { 21 int uu=u[i],vv=v[i]; 22 if(d[uu]>R&&d[vv]>R)d[uu]--,d[vv]--; 23 else if(L<=d[uu]&&d[uu]<=R&&L<=d[vv]&&d[vv]<=R)continue; 24 else if(L+1<=d[uu]&&d[uu]<=R&&d[vv]>R)d[uu]--,d[vv]--; 25 else if(d[uu]>R&&L+1<=d[vv]&&d[vv]<=R)d[uu]--,d[vv]--; 26 } 27 for(int i=1;i<=N+M;i++)if(d[i]<L||d[i]>R)flag=0; 28 printf("Case %d: %s\n",o++,flag?"Yes":"No"); 29 } 30 return 0; 31 }
给一点测试数据,网上有的贪心过不去这些数据Yes Yes Yes Yes No
4 4 16 1 3 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 4 3 6 1 2 1 1 2 1 2 2 3 1 3 1 4 3 4 4 10 1 3 1 2 1 3 2 1 2 1 2 1 3 1 3 2 3 3 4 3 4 4 3 3 7 1 1 1 2 2 3 1 3 3 2 3 3 2 1 2 1 1 3 3 1 1 1 1 1 2 1 3
官方作法
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn=1e5+5; 7 const int maxm=2e5+5; 8 const int INF=0x3f3f3f3f; 9 10 int TO[maxm],CAP[maxm],NEXT[maxm],tote; 11 int FIR[maxn],gap[maxn],cur[maxn],d[maxn],q[400000]; 12 int n,m,S,T; 13 14 void add(int u,int v,int cap) 15 { 16 //printf("i=%d u=%d v=%d cap=%d\n",tote,u,v,cap); 17 TO[tote]=v; 18 CAP[tote]=cap; 19 NEXT[tote]=FIR[u]; 20 FIR[u]=tote++; 21 22 TO[tote]=u; 23 CAP[tote]=0; 24 NEXT[tote]=FIR[v]; 25 FIR[v]=tote++; 26 } 27 void bfs() 28 { 29 memset(gap,0,sizeof gap); 30 memset(d,0,sizeof d); 31 ++gap[d[T]=1]; 32 for(int i=1;i<=n;++i)cur[i]=FIR[i]; 33 int head=1,tail=1; 34 q[1]=T; 35 while(head<=tail) 36 { 37 int u=q[head++]; 38 for(int v=FIR[u];v!=-1;v=NEXT[v]) 39 if(!d[TO[v]]) 40 ++gap[d[TO[v]]=d[u]+1],q[++tail]=TO[v]; 41 } 42 } 43 int dfs(int u,int fl) 44 { 45 if(u==T)return fl; 46 int flow=0; 47 for(int &v=cur[u];v!=-1;v=NEXT[v]) 48 if(CAP[v]&&d[u]==d[TO[v]]+1) 49 { 50 int Min=dfs(TO[v],min(fl,CAP[v])); 51 flow+=Min,fl-=Min,CAP[v]-=Min,CAP[v^1]+=Min; 52 if(!fl)return flow; 53 } 54 if(!(--gap[d[u]]))d[S]=n+1; 55 ++gap[++d[u]],cur[u]=FIR[u]; 56 return flow; 57 } 58 int ISAP() 59 { 60 bfs(); 61 int ret=0; 62 while(d[S]<=n)ret+=dfs(S,INF); 63 return ret; 64 } 65 66 int ca,N,M,Q,x,y,z,l[205][25],r[205][25]; 67 char op[2]; 68 69 void init() 70 { 71 tote=0; 72 memset(FIR,-1,sizeof FIR); 73 } 74 int main() 75 { 76 int N,M,C,L,R,u,v,s,t,ca=1; 77 while(scanf("%d%d%d",&N,&M,&C)!=EOF) 78 { 79 init(); 80 int in[6006]={0}; 81 s=N+M+1,t=s+1,S=t+1,T=S+1,n=T; 82 add(t,s,INF); 83 scanf("%d%d",&L,&R); 84 for(int i=0;i<C;i++) 85 { 86 scanf("%d%d",&u,&v); 87 add(u,N+v,1); 88 } 89 for(int i=1;i<=N;i++) 90 { 91 add(s,i,R-L); 92 in[s]-=L; 93 in[i]+=L; 94 } 95 for(int i=1;i<=M;i++) 96 { 97 add(i+N,t,R-L); 98 in[i+N]-=L; 99 in[t]+=L; 100 } 101 int sum=0; 102 for(int i=1;i<=N+M+2;i++) 103 { 104 if(in[i]>0) 105 { 106 add(S,i,in[i]); 107 sum+=in[i]; 108 } 109 else 110 add(i,T,-in[i]); 111 } 112 printf("Case %d: %s\n",ca++,sum==ISAP()?"Yes":"No"); 113 } 114 return 0; 115 }