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学长的学习笔记,
讲的十分详细:http://www.cnblogs.com/liu-runda/p/6262832.html
在你已经会来上下界网络流之后……
大概这是一道水题吧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 }