• p2057 [SHOI2007]善意的投票


    传送门

    分析

    权值不同点之间连权值为1的边

    起点向每个1,每个0向终点也连权值为1的边

    跑最小割即可

    代码

    #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 a[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 int id(int x,int y){return (x-1)*m+y;}
    inline void go(int x,int y){
        for(int i=0;i<4;i++){
          if(dx[i]+x<=0||dx[i]+x>n||dy[i]+y<=0||dy[i]+y>m)continue;
          add(id(x,y),id(dx[i]+x,dy[i]+y),inf);
        }
    }
    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",&n,&m);
        s=n+1,t=s+1;
        for(i=1;i<=n;i++){
          scanf("%d",&a[i]);
          if(a[i])add(s,i,1);
            else add(i,t,1);
        }
        for(i=1;i<=m;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          if(a[x]==a[y])continue;
          if(a[x]<a[y])swap(x,y);
          add(x,y,1);
        }
        while(bfs())while(int a=dfs(s,inf))Ans+=a;
        cout<<Ans;
        return 0;
    }
  • 相关阅读:
    记一次诡异的调优
    java动态代理学习笔记
    c#反射机制学习和利用反射获取类型信息
    php开启ssl的方法
    关于java中split的使用
    c#使用反射调用类型成员示例
    C#关于反射加载的问题
    Twitter:使用Netty 4来减少GC开销
    Java中如何修改Jar中的内容
    Android中自定义视图View之---前奏篇
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10527238.html
Copyright © 2020-2023  润新知