BZOJ 1585: Earthquake Damage 2 地震伤害 网络流 + 最小割
Description
Farmer John的农场里有P个牧场,有C条无向道路连接着他们,第i条道路连接着两个牧场Ai和Bi,注意可能有很多条道路连接着相同的Ai和Bi,并且Ai有可能和Bi相等。Farmer John在1号牧场里。由于地震,某些牧场被损坏,但由于信春哥,C条道路没有一条损坏。有N头奶牛,他们在不同的牧场里,于是N <= P。他们一一向Farmer John报告。第i头奶牛报告给Farmer John一个整数Report_i,代表第Report_i个牧场没有损毁,但不能够从第Report_i个牧场经过一些没有损坏的牧场到达1号牧场。现在Farmer John想知道,最少有多少损坏的牧场。
Input
第一行三个整数 P,C,N
第2..C+1行:每行两个整数Ai,Bi
第C+2..C+N+1行:第C+1+i行包含一个整数,Report_i
Output
一个整数,代表最少有多少损坏的牧场
题解: 最小割 + 拆点.
对于每一个点 $i$,拆成 $i$ 与 $i'$,连一条容量为 $1$ 的边,代表可以割掉. 对于原图中每一条边与没有摧毁的点,都连一条容量为无限大的边,代表不能割掉.
跑一遍最大流求一下最小割即可.
#include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #define maxn 1000000 #define inf 10000000 using namespace std; namespace Dinic{ int S,T; struct Edge{ int from,to,cap; Edge(int u,int v,int c):from(u),to(v),cap(c){} }; vector<int>G[maxn]; vector<Edge>edges; queue<int>Q; void addedge(int u,int v,int c){ edges.push_back(Edge(u,v,c)); edges.push_back(Edge(v,u,0)); int m=edges.size(); G[u].push_back(m-2); G[v].push_back(m-1); } int d[maxn],vis[maxn]; int current[maxn]; int BFS(){ memset(d,0,sizeof(d)); memset(vis,0,sizeof(vis)); d[S] = 0,vis[S] = 1; Q.push(S); while(!Q.empty()){ int u=Q.front(); Q.pop(); int m=G[u].size(); for(int i=0;i<m;++i) { Edge r = edges[G[u][i]]; if(!vis[r.to] && r.cap > 0) { d[r.to] = d[u] + 1; vis[r.to] = 1; Q.push(r.to); } } } return vis[T]; } int dfs(int x,int cur){ if(x == T) return cur; int flow=0,f; int m=G[x].size(); for(int i=current[x];i<m;++i) { current[x] = i; int u=G[x][i]; Edge r = edges[u]; if(d[r.to] == d[x] + 1 && r.cap >0) { f = dfs(r.to,min(cur,r.cap)); if(f > 0) { flow += f,cur -= f; edges[u].cap -= f,edges[u ^ 1].cap += f; } } if(cur == 0) break; } return flow; } int maxflow(){ int flow = 0; while(BFS()) { memset(current,0,sizeof(current)); flow += dfs(S,inf); } return flow; } }; int vis[maxn]; #define row1(i) (i) #define row2(i) (i + n) int main() { // setIO("input"); int n,m,k,s,t; scanf("%d%d%d",&n,&m,&k); for(int i=1,u,v;i<=m;++i) { scanf("%d%d",&u,&v); Dinic::addedge(row2(u), row1(v), inf); Dinic::addedge(row2(v), row1(u), inf); } s=row2(n+3),t = 1; Dinic::S=s; Dinic::T=t; for(int i=1,a;i<=k;++i) { scanf("%d",&a), vis[a]=1; Dinic::addedge(s, row1(a), inf); } for(int i=1;i<=n;++i) { if(vis[i]) { Dinic::addedge(row1(i), row2(i), inf); } else { Dinic::addedge(row1(i), row2(i), 1); } } printf("%d\n",Dinic::maxflow()); }