BZOJ2502:清理雪道(有上下界最小流)
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
Solution
每条边的流量界限为$[1,INF]$。 拓扑图的起点和$s$连一下,终点和$t$连一下,上下界为$[0,INF]$。
跑一遍最小流就完事了……
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 #define N (209) 6 #define INF (0x7f7f7f7f) 7 using namespace std; 8 9 struct Edge{int to,next,flow;}edge[N*N]; 10 int n,m,x,vis[N]; 11 int s,t,ss=200,tt=201,Depth[N],A[N]; 12 int head[N],num_edge; 13 queue<int>q; 14 15 inline int read() 16 { 17 int x=0,w=1; char c=getchar(); 18 while (!isdigit(c)) {if (c=='-') w=-1; c=getchar();} 19 while (isdigit(c)) x=x*10+c-'0', c=getchar(); 20 return x*w; 21 } 22 23 void add(int u,int v,int l) 24 { 25 edge[++num_edge].to=v; 26 edge[num_edge].next=head[u]; 27 edge[num_edge].flow=l; 28 head[u]=num_edge; 29 } 30 31 void Add(int u,int v,int l,int r) 32 { 33 add(u,v,r-l); add(v,u,0); 34 A[u]-=l; A[v]+=l; 35 } 36 37 int DFS(int x,int low,int t) 38 { 39 if (x==t || !low) return low; 40 int f=0; 41 for (int i=head[x]; i; i=edge[i].next) 42 if (Depth[edge[i].to]==Depth[x]+1) 43 { 44 int Min=DFS(edge[i].to,min(low,edge[i].flow),t); 45 edge[i].flow-=Min; 46 edge[((i-1)^1)+1].flow+=Min; 47 f+=Min; low-=Min; 48 if (!low) break; 49 } 50 if (!f) Depth[x]=-1; 51 return f; 52 } 53 54 bool BFS(int s,int t) 55 { 56 memset(Depth,0,sizeof(Depth)); 57 Depth[s]=1; q.push(s); 58 while (!q.empty()) 59 { 60 int x=q.front(); q.pop(); 61 for (int i=head[x]; i; i=edge[i].next) 62 if (!Depth[edge[i].to] && edge[i].flow) 63 { 64 Depth[edge[i].to]=Depth[x]+1; 65 q.push(edge[i].to); 66 } 67 } 68 return Depth[t]; 69 } 70 71 int Dinic(int s,int t) 72 { 73 int ans=0; 74 while (BFS(s,t)) ans+=DFS(s,INF,t); 75 return ans; 76 } 77 78 int main() 79 { 80 n=read(); s=0; t=n+1; 81 for (int i=1; i<=n; ++i) 82 { 83 m=read(); 84 if (!m) Add(i,t,0,INF); 85 for (int j=1; j<=m; ++j) 86 vis[x=read()]=1, Add(i,x,1,INF); 87 } 88 for (int i=1; i<=n; ++i) if (!vis[i]) Add(s,i,0,INF); 89 int sum=0; 90 for (int i=0; i<=n+1; ++i) 91 if (A[i]>0) sum+=A[i], add(ss,i,A[i]), add(i,ss,0); 92 else add(i,tt,-A[i]), add(tt,i,0); 93 add(t,s,INF); add(s,t,0); 94 Dinic(ss,tt); 95 for (int i=head[ss]; i; i=edge[i].next) edge[i].flow=edge[((i-1)^1)+1].flow=0; 96 for (int i=head[tt]; i; i=edge[i].next) edge[i].flow=edge[((i-1)^1)+1].flow=0; 97 int flow0=edge[num_edge].flow; 98 edge[num_edge-1].flow=edge[num_edge].flow=0; 99 printf("%d\n",flow0-Dinic(t,s)); 100 }