【2018沈阳赛区网络预选赛J题】Fantastic Graph 【有上下界的网络流】
要补的题太多了导致最近没写博客(好吧是我懒)
题目链接https://nanti.jisuanke.com/t/31447
题意
给出一个二分图,问能否挑选出一些边,使得每个点的度数都在[L,R]这个范围以内。
分析
标签是easy。只要会上下界网络流应该都能写出来。
开一个源点s和一个汇点t,对于每个N点,从s连一条[L,R]的边,对于每一个M点,连向t一条[L,R]的边,对于图中原本的NM之间的边,连一条[0,1]的边,然后跑有源汇点有上下界的网络流就可以。
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 int n,m,s,t,sz; 13 int head[maxn],Next[maxm*2],to[maxm*2],cap[2*maxm],flow[2*maxm]; 14 int vis[maxn],d[maxn],cur[maxn]; 15 void init(int n){ 16 this->n=n; 17 sz=-1; 18 memset(head,-1,sizeof(head)); 19 } 20 void add_edge(int a,int b,int c){ 21 ++sz; 22 to[sz]=b;cap[sz]=c;flow[sz]=0; 23 Next[sz]=head[a];head[a]=sz; 24 ++sz; 25 to[sz]=a;cap[sz]=c;flow[sz]=c; 26 Next[sz]=head[b];head[b]=sz; 27 } 28 bool BFS(){ 29 memset(vis,0,sizeof(vis)); 30 queue<int>q; 31 vis[s]=1;q.push(s); 32 d[s]=0; 33 while(!q.empty()){ 34 int u=q.front();q.pop(); 35 for(int i=head[u];i!=-1;i=Next[i]){ 36 int v=to[i]; 37 if(!vis[v]&&cap[i]>flow[i]){ 38 vis[v]=1; 39 d[v]=d[u]+1; 40 q.push(v); 41 } 42 } 43 } 44 return vis[t]; 45 } 46 int DFS(int x,int a){ 47 if(x==t||a==0)return a; 48 int Flow=0,f; 49 for(int &i=cur[x];i!=-1;i=Next[i]){ 50 int v=to[i]; 51 if(d[v]==d[x]+1&&(f=DFS(v,min(a,cap[i]-flow[i])))>0){ 52 Flow+=f; 53 flow[i]+=f; 54 flow[i^1]-=f; 55 a-=f; 56 if(a==0)break; 57 } 58 } 59 return Flow; 60 } 61 int Maxflow(int s,int t){ 62 this->s=s,this->t=t; 63 int Flow=0; 64 while(BFS()){ 65 for(int i=0;i<=n;i++) 66 cur[i]=head[i]; 67 Flow+=DFS(s,INF); 68 69 } 70 //printf("!!%d\n",Flow); 71 return Flow; 72 } 73 }dinic; 74 int N,M,K,L,R,sum,kase; 75 int du[maxn]; 76 int main(){ 77 kase=0; 78 while(scanf("%d%d%d",&N,&M,&K)!=EOF){ 79 ++kase; 80 memset(du,0,sizeof(du)); 81 scanf("%d%d",&L,&R); 82 dinic.init(N+M+4); 83 for(int i=1;i<=N;i++){ 84 dinic.add_edge(0,i,R-L); 85 du[i]+=L;du[0]-=L; 86 } 87 sum=0; 88 for(int i=1;i<=M;i++){ 89 dinic.add_edge(i+N,N+M+1,R-L); 90 du[i+N]-=L;du[N+M+1]+=L; 91 } 92 int a,b; 93 for(int i=1;i<=K;i++){ 94 scanf("%d%d",&a,&b); 95 dinic.add_edge(a,b+N,1); 96 } 97 dinic.add_edge(N+M+1,0,INF); 98 int s=N+M+2,t=N+M+3; 99 for(int i=0;i<=N+M+1;i++){ 100 if(du[i]>0){ 101 sum+=du[i]; 102 dinic.add_edge(s,i,du[i]); 103 } 104 if(du[i]<0){ 105 dinic.add_edge(i,t,-du[i]); 106 } 107 } 108 int maxflow=dinic.Maxflow(s,t); 109 // printf("%d %d\n",maxflow,sum); 110 printf("Case %d: ",kase); 111 if(maxflow==sum){ 112 printf("Yes\n"); 113 }else{ 114 printf("No\n"); 115 } 116 } 117 return 0; 118 }