[CTSC1999]家园

xiaoxiao2021-02-28  15

题目链接:https://www.luogu.org/problemnew/show

这是一道分层图最大流问题

样例的分层图大概长这样↓

按时间分层,连边,跑最大流即可,dinic利用残量网络可以跑得更快一些。

对于无解的判断可以用并查集。

上代码↓

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=2e9; int n,m,s,t,np=1,p,mfl; int l[21][21],f[21],h[5005],cur[5005],tp[5005],q[50050]; struct rpg{ int li,nx,ln; }a[50050]; void add(int ls,int nx,int ln){ a[++np]=(rpg){h[ls],nx,ln}; h[ls]=np; a[++np]=(rpg){h[nx],ls,0}; h[nx]=np; } int find(int x){ if(f[x]==x) return x; else return f[x]=find(f[x]); }void un(int a,int b){ int fa=find(a),fb=find(b); if(fa!=fb) f[fa]=fb; } bool bfs(int ps){ memset(tp,0,sizeof(tp)); int hd=1,tl=1; q[hd]=s; tp[s]=1; while(hd<=tl){ int nw=q[hd++]; for(int i=h[nw];i;i=a[i].li){ if(a[i].ln&&!tp[a[i].nx]){ tp[a[i].nx]=tp[nw]+1; q[++tl]=a[i].nx; } } }return tp[t]; } int dfs(int u,int maxn){ if(u==t||!maxn) return maxn; int sum=0; for(int& i=cur[u];i;i=a[i].li){ if(a[i].ln&&tp[a[i].nx]==tp[u]+1){ int f=dfs(a[i].nx,min(maxn,a[i].ln)); if(f){ maxn-=f; sum+=f; a[i].ln-=f; a[i^1].ln+=f; if(!maxn) break; } } }return sum; } void dnc(int ps){ while(bfs(ps)){ for(int i=0;i<=ps;++i) cur[i]=h[i]; while(int d=dfs(s,INF)) mfl+=d; } } int main(){ scanf("%d%d%d",&n,&l[0][0],&p);t=n+1; for(int i=1;i<=n+1;++i) f[i]=i; for(int i=1;i<=l[0][0];++i){ scanf("%d%d",&l[0][i],&l[i][0]); for(int j=1;j<=l[i][0];++j){ scanf("%d",&l[i][j]); if(l[i][j]==-1) l[i][j]=n+1; if(j>1) un(l[i][j],l[i][j-1]); } }if(find(0)!=find(n+1)){ puts("0"); return 0; } for(int ti=1;;++ti){ for(int i=0;i<=n;++i){ add(i+(ti-1)*(n+2),i+ti*(n+2),INF); }add(n+1+ti*(n+2),n+1+(ti-1)*(n+2),INF); for(int i=1;i<=l[0][0];++i){ int tmp=(ti-1)%l[i][0]+1; add(l[i][tmp]+(ti-1)*(n+2),l[i][ti%l[i][0]+1]+ti*(n+2),l[0][i]); } dnc((ti+1)*(n+2)); if(mfl>=p){ printf("%d\n",ti); return 0; } }return 0; }
转载请注明原文地址: https://www.6miu.com/read-1650233.html

最新回复(0)