ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph (有源汇上下界网络流)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37025443/article/details/82588997

题目链接

题意:

给你一张二分图,一边n个点,另一边m个点,k条边,问你能不能通过删边,使得所有点的度数都在[L,R]

解析:

有源汇上下界网络流模板题

算法链接

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=4005,maxm=120005;
const int inf=0x7f7f7f7f;
struct edge{
  int to,next,w,num;
}lst[maxm];int len=0,first[maxn],_first[maxn];
void addedge(int a,int b,int w,int num){
  lst[len].num=num;
  lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++;
  lst[len].num=num;
  lst[len].to=a;lst[len].next=first[b];lst[len].w=0;first[b]=len++;
}
int q[maxn],vis[maxn],dis[maxn],T,s,t,head,tail,ss,tt;
bool bfs(){
  head=tail=0;vis[s]=++T;q[tail++]=s;
  while(head!=tail){
    int x=q[head++];
    for(int pt=first[x];pt!=-1;pt=lst[pt].next){
      if(lst[pt].w&&vis[lst[pt].to]!=T){
    vis[lst[pt].to]=T;dis[lst[pt].to]=dis[x]+1;q[tail++]=lst[pt].to;
      }
    }
  }
  if(vis[t]==T)memcpy(_first,first,sizeof(first));
  return vis[t]==T;
}
int dfs(int x,int lim){
  if(x==t)return lim;
  int flow=0,a;
  for(int pt=_first[x];pt!=-1;pt=lst[pt].next){
    _first[x]=pt;
    if(lst[pt].w&&dis[lst[pt].to]==dis[x]+1&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))){
      lst[pt].w-=a;lst[pt^1].w+=a;flow+=a;
      if(flow==lim)return flow;
    }
  }
  return flow;
}
int dinic(){
  int ans=0,x;
  while(bfs())
    while(x=dfs(s,inf))ans+=x;
  return ans;
}
int totflow[maxn];
void Add(int a,int b,int lo,int hi,int num){
  totflow[a]-=lo;totflow[b]+=lo;
  addedge(a,b,hi-lo,num);
}
int low[maxm],ans[maxm];
int n,m,tot;
void bound_flow(){
  int sum=0;
  for(int i=s;i<=t;++i){
    if(totflow[i]<0){
      addedge(i,tt,-totflow[i],0);
    }else{
      sum+=totflow[i];
      addedge(ss,i,totflow[i],0);
    }
  }
  addedge(t,s,0x7f7f7f7f,0);
  int tmps=s,tmpt=t;
  s=ss;t=tt;
  if(dinic()==sum){
	  printf("Yes\n");
  }else{
      printf("No\n");
  }
}

int k;
int L,R;
int cas;
void work(){
  cas++;
  
  scanf("%d%d",&L,&R);
  s=0;t=n+m+1;
  ss=n+m+2;tt=n+m+3;
  memset(first,-1,sizeof(first));len=0;
  memset(totflow,0,sizeof(totflow));
  int x,y;
  for(int i=1;i<=n;++i){
     Add(s,i,L,R,0);
  }
  for(int i=1;i<=m;i++){
	  Add(i+n,t,L,R,0);
  }
  int l,h;
  tot=0;
  for(int i=1;i<=k;++i){
    scanf("%d%d",&x,&y);
    //Add(s,i,0,y,0);
    
    Add(x,n+y,0,1,tot);low[tot]=0;
    
  }
  printf("Case %d: ",cas);
  bound_flow();
}
int main(){
  while(scanf("%d%d%d",&n,&m,&k)!=EOF)work();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/82588997