网络流/上下界网络流
带下界的最小可行流……
我SB了,跑网络流的时候是得从虚拟源0往出跑……而不是S……
Orz Hzwer
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /************************************************************** 2 Problem: 2502 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:3080 ms 7 Memory:10652 kb 8 ****************************************************************/ 9 10 //BZOJ 2502 11 #include<vector> 12 #include<cstdio> 13 #include<cstdlib> 14 #include<cstring> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 using namespace std; 21 int getint(){ 22 int v=0,sign=1; char ch=getchar(); 23 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 24 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 25 return v*sign; 26 } 27 typedef long long LL; 28 const int N=100010,M=500010,INF=~0u>>2; 29 /*******************tamplate********************/ 30 int n,m,ans; 31 struct edge{int to,v;}; 32 struct Net{ 33 edge E[M]; 34 int head[N],next[M],cnt; 35 void ins(int x,int y,int z){ 36 E[++cnt]=(edge){y,z}; 37 next[cnt]=head[x]; head[x]=cnt; 38 } 39 void add(int x,int y,int z){ 40 ins(x,y,z); ins(y,x,0); 41 } 42 int S,T,d[N],cur[N],Q[M]; 43 bool mklevel(){ 44 int l=0,r=-1; 45 F(i,0,T) d[i]=-1; 46 d[0]=0; Q[++r]=0; 47 while(l<=r){ 48 int x=Q[l++]; 49 for(int i=head[x];i;i=next[i]) 50 if(E[i].v && d[E[i].to]==-1){ 51 d[E[i].to]=d[x]+1; 52 Q[++r]=E[i].to; 53 } 54 } 55 return d[T]!=-1; 56 } 57 int dfs(int x,int a){ 58 if (x==T) return a; 59 int flow=0; 60 for(int &i=cur[x];i && flow<a;i=next[i]) 61 if (E[i].v && d[E[i].to]==d[x]+1){ 62 int f=dfs(E[i].to,min(E[i].v,a-flow)); 63 E[i].v-=f; 64 E[i^1].v+=f; 65 flow+=f; 66 } 67 if (!flow) d[x]=-1; 68 return flow; 69 } 70 void Dinic(){ 71 while(mklevel()){ 72 F(i,0,T) cur[i]=head[i]; 73 ans+=dfs(0,INF); 74 } 75 } 76 int in[N]; 77 void init(){ 78 n=getint(); cnt=1; m=0; 79 F(i,1,n){ 80 int x=getint(),y; 81 F(j,1,x){ 82 y=getint(); m++; 83 add(i,n+2*m-1,INF); 84 add(n+2*m,y,INF); 85 } 86 } 87 S=n+m+m+1; T=S+1; ans=0; 88 F(i,1,m){ 89 add(n+2*i-1,n+2*i,INF); 90 in[n+2*i-1]--; in[n+2*i]++; 91 } 92 F(i,1,n) add(S,i,INF); 93 F(i,n+1,n+m+m) 94 if(in[i]>0) add(0,i,in[i]); 95 else add(i,T,-in[i]); 96 for(int i=1;;i++){ 97 add(0,S,1); 98 Dinic(); 99 if (ans==m){printf("%d\n",i);break;} 100 } 101 } 102 }G1; 103 int main(){ 104 #ifndef ONLINE_JUDGE 105 freopen("input.txt","r",stdin); 106 // freopen("output.txt","w",stdout); 107 #endif 108 G1.init(); 109 return 0; 110 }
2502: 清理雪道
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 182 Solved: 96
[Submit][Status][Discuss]
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
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0
Sample Output
4