网络流24题13
https://loj.ac/problem/6015
着重理解这题的建图是按照时间的分层图,对于时刻t的n个站点,他们的人员有2种来源 ,一是上一个时刻停留在该点的人员,另一种就是t-1通过飞船过来的人,对于每个新时刻维护好这几个边就行了
然后并查集判断有无解
#include <iostream> #include <stdio.h> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include <map> using namespace std; const int maxn = 50; const int inf = 0x3f3f3f3f; int fa[maxn]; int cap[maxn]; int head[maxn*1000]; int all[maxn]; struct edge{ int v,nex,w; }e[maxn*1000]; int tot = 0; void addedge(int u,int v,int w){ e[tot] = (edge){v,head[u],w}; head[u] = tot++; e[tot] = (edge){u,head[v],0}; head[v] = tot++; } vector<int> v[maxn]; int find(int now){ if(fa[now]== now) return now; return find(fa[now]); } void un(int u,int v){ int fau = find(u); int fav = find(v); if(fau!=fav){ fa[fau] = fa[fav]; } } int deep[maxn*100]; bool bfs(int S,int T){ memset(deep, 0, sizeof(deep)); deep[S] = 1; queue<int> q; q.push(S); while (!q.empty()) { int now = q.front(); q.pop(); for(int i=head[now];i!=-1;i=e[i].nex){ int w = e[i].w; int v = e[i].v; if(deep[v]!=0 || w<=0) continue; deep[v] = deep[now]+1; q.push(v); } } return deep[T]; } int dfs(int now,int T,int maxflow){ if(now==T) return maxflow; int all = 0; for(int i=head[now];i!=-1 && all<maxflow;i=e[i].nex){ int v = e[i].v; int w = e[i].w; if(deep[v]!=deep[now]+1 || w<=0) continue; int tt = dfs(v,T,min(maxflow-all,w)); e[i].w-=tt; e[i^1].w+=tt; all+=tt; } return all; } int main(int argc, const char * argv[]) { memset(head, -1, sizeof(head)); int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i=0;i<=n+1;i++){ fa[i] = i; } int S = 0; int T = 1; for(int i=0;i<m;i++){ scanf("%d",&cap[i]); scanf("%d",&all[i]); for(int j=0;j<all[i];j++){ int tmp ; scanf("%d",&tmp); tmp++; v[i].push_back(tmp); if(j!=0){ un(v[i][0],tmp); } } } if(find(0)!=find(1)){ puts("0"); return 0; } int ans; int maxflow = 0; addedge(S, 1+1*(n+2), inf); addedge(1*(n+2), T, inf); for(int i=0;i<n+2;i++){ addedge(i+1*(n+2), i+(1+1)*(n+2), inf); } for(ans=2;;ans++){ addedge(S, 1+ans*(n+2), inf); addedge(ans*(n+2), T, inf); for(int i=0;i<m;i++){ int from = v[i][(ans-2+all[i])%all[i]]; int to = v[i][(ans-1+all[i])%all[i]]; addedge(from+(ans-1)*(n+2), to+ans*(n+2), cap[i]); } while (bfs(S,T)) { maxflow+=dfs(S,T,inf); } if(maxflow>=k) break; for(int i=0;i<n+2;i++){ addedge(i+ans*(n+2), i+(ans+1)*(n+2), inf); } } printf("%d\n",ans-1); return 0; }