zoukankan      html  css  js  c++  java
  • p2944 [USACO09MAR]地震损失2Earthquake Damage 2

    传送门

    分析

    我们让s到1,关键点到t分别连流量为inf的边

    于是我们可以考虑跑s到t的最小割

    于是我们将所有点拆为两个点,关键点和1的两个点之间连inf,其余点连1

    将原图的边也连上,流量为inf

    于是跑最小割即可

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<ctime>
    #include<queue>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    const int dx[] = {1,-1,0,0};
    const int dy[] = {0,0,1,-1};
    const int inf = 1e9+7;
    int n,m,s,t,head[2000100],to[2000100],nxt[2000100],w[2000100],ano[2000100],cnt,level[2000100],cur[2000100];
    int used[2000100];
    inline void add(int x,int y,int z){
        nxt[++cnt]=head[x];
        head[x]=cnt;
        to[cnt]=y;
        w[cnt]=z;
        ano[cnt]=cnt+1;
        nxt[++cnt]=head[y];
        head[y]=cnt;
        to[cnt]=x;
        w[cnt]=0;
        ano[cnt]=cnt-1;
    }
    inline bool bfs(){
        memset(level,-1,sizeof(level));
        queue<int>q;
        level[s]=0;
        q.push(s);
        while(!q.empty()){
          int x=q.front();
          q.pop();
          for(int i=head[x];i;i=nxt[i])
            if(level[to[i]]==-1&&w[i]){
              level[to[i]]=level[x]+1;
              if(to[i]==t)return 1;
              q.push(to[i]);
            }
        }
        return 0;
    }
    inline int dfs(int x,int flow){
        if(x==t||!flow)return flow;
        int res=0;
        cur[x]=head[x];
        for(int i=cur[x];i;i=nxt[i]){
          cur[x]=i;
          if(level[to[i]]==level[x]+1&&w[i]){
              int f=dfs(to[i],min(w[i],flow-res));
              w[i]-=f;
              res+=f;
              w[ano[i]]+=f;
          }
        }
        if(!res)level[x]=-1;
        return res;
    }
    int main(){
        int i,j,k,Ans=0;
        scanf("%d%d%d",&n,&m,&k);
        s=2*n+1,t=s+1;
        add(s,1,inf);
        add(1,n+1,inf);
        for(i=1;i<=m;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          add(x+n,y,inf);
          add(y+n,x,inf);
        }
        for(i=1;i<=k;i++){
          int x;
          scanf("%d",&x);
          add(x+n,t,inf);
          add(x,x+n,inf);
          used[x]=1;
        }
        for(i=2;i<=n;i++){
          if(used[i])continue;
          add(i,i+n,1);
        }
        while(bfs())while(int a=dfs(s,inf))Ans+=a;
        cout<<Ans;
        return 0;
    }
  • 相关阅读:
    树状数组
    #135. 二维树状数组 3:区间修改,区间查询
    poj 2155 (二维树状数组 区间修改 求某点值)
    #133. 二维树状数组 1:单点修改,区间查询
    poj 3468 (区间修改 区间查询)
    树状数组 模板
    1535:【例 1】数列操作
    最通俗全面理解application context中的context是什么意思
    牛客哈理工小乐乐下象棋(深度理解bfs好题)
    牛客哈理工小乐乐打游戏(bfs深度理解好题)
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10562688.html
Copyright © 2011-2022 走看看