【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 }
View Code

猜你喜欢

转载自www.cnblogs.com/LQLlulu/p/9616564.html