ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph (有源汇上下界网络流板子)
板子题
给你一张二分图,一边n个点,另一边m个点,k条边,问你能不能通过删边,使得所有点的度数都在[L,R]
#include<bits/stdc++.h> #define FIN freopen("input.txt","r",stdin) #define ll long long #define mod 1000000007 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define inf 0x3f3f3f3f #define INF 0x3f3f3f3f3f3f3f3f const int maxn = 100005; using namespace std; int cnt,s,t,n,m,k; int head[maxn],Next[maxn*20],to[maxn*20]; int flow[maxn*20],dep[maxn],cur[maxn],mp[405][405]; int dir[8][2]={1,2,1,-2,-1,2,-1,-2,-2,-1,-2,1,2,1,2,-1}; inline void add(int u,int v,int w){ Next[cnt]=head[u]; head[u]=cnt; to[cnt]=v; flow[cnt++]=w; Next[cnt]=head[v]; head[v]=cnt; to[cnt]=u; flow[cnt++]=0; } int dfs(int u,int cost){ if(u==t) return cost; for(int &i=cur[u];i!=-1;i=Next[i]){ if(dep[to[i]]==dep[u]+1&&flow[i]>0){ int dis=dfs(to[i],min(flow[i],cost)); if(dis>0){ flow[i]-=dis; flow[i^1]+=dis; return dis; } } } return 0; } int bfs(){ queue<int> q; q.push(s); memset(dep,0,sizeof(dep)); dep[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=Next[i]){ if(flow[i]>0&&dep[to[i]]==0){ dep[to[i]]=dep[u]+1; q.push(to[i]); } } } if(dep[t]>0) return 1; return 0; } int dicnic(){ int ans=0; while(bfs()){ int cost; for(int i=0;i<=t+2;i++){ cur[i]=head[i]; } while(cost=dfs(s,inf)) ans+=cost; } return ans; } int p[200005]; void init(){ memset(head,-1,sizeof(head)); memset(p,0,sizeof(p)); cnt=0; } int main(){ int cas=0; while(~scanf("%d %d %d",&n,&m,&k)){ init(); int l,r; int ss=0; //源点 int tt=n+m+1;//汇点 s=n+m+2;//超级源点 t=n+m+3;//超级汇点 int sum=0; scanf("%d %d",&l,&r); for(int i=1;i<=k;i++){ int u,v; scanf("%d %d",&u,&v); add(u,v+n,1); } for(int i=1;i<=n;i++){ add(ss,i,r-l); p[i]+=l; } for(int i=1;i<=m;i++){ add(i+n,tt,r-l); p[i+n]-=l; } for(int i=1;i<=n+m;i++){ if(p[i]<0) add(i,t,-p[i]); else add(s,i,p[i]),sum+=p[i]; // printf("%d ---> %d\n", i,p[i]); } add(tt,ss,inf); printf("Case %d: ",++cas); if(sum==dicnic()) puts("Yes"); else puts("No"); } }