题意:
给出一个二分图,初始各个点度数均为0,每选择一条边,则相应的两点的度数+1,并给出上下界L~R,求能否构成一个网络,使每个点的度数都在L~R之间
思路:
有源汇上下界可行流,先添加一个源点连接所有左侧点,添加一个汇点,使所有右侧点连向汇点,根据上下界网络流做法,还需添加一个附加源点和附加汇点,表示必要弧
具体方法讲解见https://blog.csdn.net/u011008379/article/details/38306477
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<iostream>
using namespace std;
const int N=1e5+7;
const int inf=0x3f3f3f3f;
struct node
{
int to,next,cost;
}e[30*N];
int eid,p[N],c[N];
void init()
{
eid=0;
memset(p,-1,sizeof(p));
memset(c,-1,sizeof(c));
}
void insert(int u,int v,int w)
{
e[eid].to=v;
e[eid].cost=w;
e[eid].next=p[u];
p[u]=eid++;
}
void addedge(int u,int v,int w)
{
insert(u,v,w);
insert(v,u,0);
}
int n,m,sp,tp;
int d[N];
bool bfs() //构建层次
{
memset(d,-1,sizeof(d));
queue<int>Q;
d[sp]=0;
Q.push(sp);
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for(int i=p[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(d[v]==-1&&e[i].cost){
d[v]=d[u]+1;
Q.push(v);
if(v==tp) return true;
}
}
}
return ~d[tp];
}
int dfs(int u,int b)
{
if(u==tp) return b;
int r=0;
for(int i=c[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(e[i].cost&&d[v]==d[u]+1){
int x=min(e[i].cost,b-r);
c[u]=i;
x=dfs(v,x);
r+=x;
e[i].cost-=x;
e[i^1].cost+=x;
if(r==b) break;
}
}
if(!r)d[u]=-2;
return r;
}
int dinic(){
int total=0,tmp;
while(bfs()){
memcpy(c,p,sizeof(p));
while(tmp=dfs(sp,inf))
total+=tmp;
}
return total;
}
int x[N];
int main()
{
int k,L,R,cs=0;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
init();
sp=n+m+1,tp=n+m+2; //附加源,附加汇
int ss=n+m+3,tt=n+m+4; //源点,汇点
scanf("%d%d",&L,&R);
int u,v;
for(int i=1;i<=k;i++){
scanf("%d%d",&u,&v);
addedge(u,v+n,1); //构建网络,左边点编号为1~n,右边点编号为n+1~2*n
}
for(int i=1;i<=n;i++){
addedge(ss,i,R-L); //源点连向所有左侧点,修改流量为R-L
addedge(sp,i,L); //附加源连向所有左侧点,流量为L,表示必要弧
addedge(ss,tp,L); //源点连向附加汇
}
for(int i=1;i<=m;i++){
addedge(i+n,tt,R-L); //右侧点连向汇点,修改流量为R-L
addedge(sp,tt,L); //附加源连向汇点
addedge(i+n,tp,L); //右侧点连向附加汇,流量为L,表示必要弧
}
addedge(tt,ss,inf); //汇点到源点连一条流量为inf的边,变为有源上下界网络流
printf("Case %d: ",++cs);
if(dinic()==(n+m)*L) puts("Yes"); //求附加源到附加汇的最大流,若满足附加源到附加汇的所有弧都满流,则有可行流
else puts("No");
}
return 0;
}