[有源汇最小流] Bzoj P2502 清理雪道
Description
滑雪场坐落在FJ省西北部的若干座山上。
从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
Input
Output
输出文件的第一行是一个整数k – 直升飞机的最少飞行次数。
Sample Input
8
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0
Sample Output
4
题解
- s向每个点连[0,inf)的边,每个点向t连[0,inf)的边
- 每条边的流量限制为[1,inf)
- 对(s,t)跑最小流即可
代码
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 #define N 225 7 #define inf 0x3f3f3f3f 8 using namespace std; 9 int n,cnt=1,s,t,ss,tt,ans,head[N],dis[N],d[N]; 10 struct edge{int to,c,from;}e[N*N*5]; 11 queue<int>Q; 12 void insert(int x,int y,int z) 13 { 14 e[++cnt].to=y,e[cnt].c=z,e[cnt].from=head[x],head[x]=cnt; 15 e[++cnt].to=x,e[cnt].c=0,e[cnt].from=head[y],head[y]=cnt; 16 } 17 bool bfs() 18 { 19 memset(dis,0,sizeof(dis)),dis[ss]=1; 20 while (!Q.empty()) Q.pop(); 21 Q.push(ss); 22 while (!Q.empty()) 23 { 24 int u=Q.front(); Q.pop(); 25 for (int i=head[u];i;i=e[i].from) 26 if (e[i].c&&!dis[e[i].to]) 27 { 28 dis[e[i].to]=dis[u]+1; 29 if (e[i].to==tt) return 1; 30 Q.push(e[i].to); 31 } 32 } 33 return 0; 34 } 35 int dfs(int x,int maxf) 36 { 37 if (x==tt||!maxf) return maxf; 38 int r=0; 39 for (int i=head[x];i;i=e[i].from) 40 if (e[i].c&&dis[e[i].to]==dis[x]+1) 41 { 42 int f=dfs(e[i].to,min(maxf-r,e[i].c)); 43 e[i].c-=f,e[i^1].c+=f,r+=f; 44 if (r==maxf) break; 45 } 46 return r; 47 } 48 int main() 49 { 50 scanf("%d",&n); 51 for (int i=1,x,y;i<=n;i++) 52 { 53 scanf("%d",&x); 54 for (int j=1;j<=x;j++) scanf("%d",&y),d[i]--,d[y]++,insert(i,y,inf); 55 } 56 s=n+1,t=s+1,ss=t+1,tt=ss+1; 57 for (int i=1;i<=n;i++) 58 { 59 insert(s,i,inf),insert(i,t,inf); 60 if (d[i]>0) insert(ss,i,d[i]); else if (d[i]<0) insert(i,tt,-d[i]); 61 } 62 insert(t,s,inf); 63 while (bfs()) dfs(ss,inf); 64 ans=e[cnt].c,e[cnt].c=e[cnt^1].c=0; 65 for (int i=head[ss];i;i=e[i].from) e[i].c=e[i^1].c=0; 66 for (int i=head[tt];i;i=e[i].from) e[i].c=e[i^1].c=0; 67 insert(ss,t,inf),insert(s,tt,inf); 68 while (bfs()) ans-=dfs(ss,inf); 69 printf("%d",ans); 70 }