[有源汇最小流] Bzoj P2502 清理雪道

Description

       滑雪场坐落在FJ省西北部的若干座山上。
从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
 

Input

 
输入文件的第一行包含一个整数n (2 <= n <= 100) – 代表滑雪场的地点的数量。接下来的n行,描述1~n号地点出发的斜坡,第i行的第一个数为mi (0 <= mi < n) ,后面共有mi个整数,由空格隔开,每个整数aij互不相同,代表从地点i下降到地点aij的斜坡。每个地点至少有一个斜坡与之相连。

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 }

 

posted @ 2019-07-08 10:22  BEYang_Z  阅读(197)  评论(1编辑  收藏  举报