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()); 
}

  

posted @ 2019-06-05 11:14  EM-LGH  阅读(187)  评论(0编辑  收藏  举报