计蒜课: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" 

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=4100;
struct edge{
    int from,to,cap,flow;
    edge(int a,int b,int c,int d){from=a,to=b,cap=c,flow=d;}
};
vector<int>g[N];vector<edge>ed;
void add(int from,int to,int cap){
    ed.push_back(edge(from,to,cap,0));
    ed.push_back(edge(to,from,0,0));
    int m=ed.size();
    g[from].push_back(m-2);
    g[to].push_back(m-1);
}
int dep[N],cur[N],du[N];
int n,m,k;
bool bfs(int s,int t){
    memset(dep,-1,sizeof(dep));
    queue<int>q;dep[s]=0;q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=0;i<g[u].size();i++){
            edge v=ed[g[u][i]];
            if(v.cap>v.flow&&dep[v.to]==-1){
                dep[v.to]=dep[u]+1;
                if(v.to==t) return true;
                q.push(v.to);
            }
        }
    }
    return false;
}
int dfs(int s,int t,int del){
    if(s==t) return del;
    int tmp;
    for(int &i=cur[s];i<g[s].size();i++){
        edge &v=ed[g[s][i]];
        if(dep[v.to]==dep[s]+1&&v.cap>v.flow){
            tmp=dfs(v.to,t,min(del,v.cap-v.flow));
            if(tmp>0){
                v.flow+=tmp;
                ed[g[s][i]^1].flow-=tmp;
                return tmp;
            }
        }
    }
    return 0;
}
int dinic(int s,int t){
    int ans=0,tmp;
    while(bfs(s,t)){
        memset(cur,0,sizeof(cur));
        while(tmp=dfs(s,t,INF)) ans+=tmp;
    }
    return ans;
}
int main(){
    int sum=0,l,r,x,y;int _=0;
    while(~scanf("%d%d%d",&n,&m,&k)){
        scanf("%d%d",&l,&r);memset(du,0,sizeof(du));
        for(int i=1;i<N;i++) g[i].clear();ed.clear();sum=0;
        for(int i=1;i<=n;i++){add(0,i,r-l);du[0]-=l;du[i]+=l;}
        for(int i=1;i<=m;i++){add(n+i,n+m+1,r-l);du[n+i]-=l;du[n+m+1]+=l;}
        for(int i=1;i<=k;i++){scanf("%d%d",&x,&y);add(x,n+y,1);}
        int s=n+m+2,t=n+m+3;add(n+m+1,0,INF);
        for(int i=0;i<=n+m+1;i++){
            if(du[i]>0){sum+=du[i];add(s,i,du[i]);}
            else if(du[i]<0){add(i,t,-du[i]);}
        } 
        int ans=dinic(s,t);
        printf("Case %d: ",++_);
        if(ans==sum) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/vainglory/p/9637236.html