[BZOJ2502]清理雪道 有上下界网络流(最小流)

2502: 清理雪道

Time Limit: 10 Sec  Memory Limit: 128 MB

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
 
题解:
 接触到的第一道上下界网络流题目……我怎么什么题都不会啊.jpg
如果你对上下界网络流没有接触的话,首先安利一波liu_runda学长的学习笔记,
在你已经会来上下界网络流之后……
大概这是一道水题吧233
先计算出附加流,然后从附加源ss跑到附加汇tt的最大流,
这样我们就得到了一个可行流,在t->s的弧上面把可行流的流量ans1提取出来。
然后我们去掉t->s的弧以及ss,tt两个附加点,再跑一边t->s最大流
由于反向边的流量增加意味着正向边的流量减少,所以设这样跑出来的最大流是ans2,答案就是ans1-ans2。
这样我们就解决了本题。代码实现:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=210,inf=0x7fffffff;
 6 struct edge{int zhong,next,flow;};
 7 struct NetWork
 8 {
 9     int n,S,T,e,adj[N],cur[N];
10     int hd,tl,que[N],dist[N],gap[N];
11     edge s[N<<6];
12     inline void intn(int sz)
13     {
14         n=sz,e=1,memset(adj,0,sizeof(adj));
15         memset(dist,0,sizeof(dist));
16         memset(gap,0,sizeof(gap));
17     }
18     inline void add(int qi,int zhong,int flow)
19         {s[++e].zhong=zhong;s[e].next=adj[qi];adj[qi]=e;s[e].flow=flow;}
20     inline void bfs()
21     {
22         hd=1,tl=0,dist[T]=1,que[++tl]=T;
23         register int i,x,u;
24         while(hd<=tl)
25             for(x=que[hd++],++gap[dist[x]],i=adj[x];i;i=s[i].next)
26                 if(!dist[s[i].zhong])
27                     dist[s[i].zhong]=dist[x]+1,que[++tl]=s[i].zhong;
28     }
29     int Shoot(int rt,int maxf)
30     {
31         if(rt==T||!maxf)return maxf;
32         register int i,f,ret=0;
33         for(i=cur[rt];i;i=s[i].next)
34             if(s[i].flow&&dist[rt]==dist[s[i].zhong]+1)
35             {
36                 f=Shoot(s[i].zhong,min(s[i].flow,maxf)),
37                 maxf-=f,ret+=f,s[i].flow-=f,s[i^1].flow+=f;
38                 if(!maxf)return ret;
39             }
40         if(!(--gap[dist[rt]]))dist[S]=n+1;
41         ++gap[++dist[rt]],cur[rt]=adj[rt];
42         return ret;
43     }
44     inline int ISAP(int a,int b)
45     {
46         S=a,T=b;int maxf=0;bfs();
47         memcpy(cur,adj,sizeof(adj));
48         while(dist[S]<=n)maxf+=Shoot(S,inf);
49         return maxf;
50     }
51     inline void cut_off(int x)
52     {
53         register int i;
54         for(i=adj[x];i;i=s[i].next)
55             s[i].flow=s[i^1].flow=0;
56     }
57     inline void get_ans(int a,int b,int ss,int tt)
58     {
59         add(b,a,inf),add(a,b,0),ISAP(ss,tt);
60         int ans=s[e].flow;
61         s[e].flow=s[e^1].flow=0;
62         cut_off(ss),cut_off(tt);
63         printf("%d\n",ans-ISAP(b,a));
64     }
65 }SAP;
66 int n,m,S,T,SS,TT;
67 int rudu[N],chudu[N],du[N];
68 int main()
69 {
70     scanf("%d",&n),S=0,T=n+1,SS=T+1,TT=SS+1;
71     SAP.intn(TT+1);
72     register int a,b,i,j;
73     for(i=1;i<=n;++i)
74         for(scanf("%d",&a),j=1;j<=a;++j)
75             scanf("%d",&b),++du[b],--du[i],
76             ++chudu[i],++rudu[b],
77             SAP.add(i,b,inf),SAP.add(b,i,0);
78     for(i=1;i<=n;++i)
79     {
80         if(!rudu[i])SAP.add(S,i,inf),SAP.add(i,S,0);
81         if(!chudu[i])SAP.add(i,T,inf),SAP.add(T,i,0);
82     }
83     for(i=1;i<=n;++i)
84     {
85         if(du[i]>0)SAP.add(SS,i,du[i]),SAP.add(i,SS,0);
86         if(du[i]<0)SAP.add(i,TT,-du[i]),SAP.add(TT,i,0);
87     }
88     SAP.get_ans(S,T,SS,TT);
89 }

 

 
 
posted @ 2017-09-24 20:38  LadyLex  阅读(296)  评论(0编辑  收藏  举报