zoukankan      html  css  js  c++  java
  • 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
    ",Dinic::maxflow()); 
    }
    

      

  • 相关阅读:
    学生管理系统初步总结
    ListView控件详解
    Windows窗体应用布局详解
    winforms控件
    指尖上的数据库之探囊取物
    指尖上的数据库之无中生有
    银行bank系统项目实践
    QT Creator 快速入门教程 读书笔记(一)
    我的程序员之路(英语的学习)
    游戏开发完整学习路线(各个版本都有)
  • 原文地址:https://www.cnblogs.com/guangheli/p/10978520.html
Copyright © 2011-2022 走看看