zoukankan      html  css  js  c++  java
  • bzoj1934

      

    1934: [Shoi2007]Vote 善意的投票

    Time Limit: 1 Sec  Memory Limit: 64 MB
    Submit: 2406  Solved: 1498
    [Submit][Status][Discuss]

    Description

    幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

    Input

    第一行只有两个整数n,m,保证有2≤n≤300,1≤m≤n(n-1)/2。其中n代表总人数,m代表好朋友的对数。文件第二行有n个整数,第i个整数代表第i个小朋友的意愿,当它为1时表示同意睡觉,当它为0时表示反对睡觉。接下来文件还有m行,每行有两个整数i,j。表示i,j是一对好朋友,我们保证任何两对i,j不会重复。

    Output

    只需要输出一个整数,即可能的最小冲突数。

    Sample Input

    3 3
    1 0 0
    1 2
    1 3
    3 2

    Sample Output

    1

    HINT

    在第一个例子中,所有小朋友都投赞成票就能得到最优解

      最小割模型。

      S向1的人建容量1的边,0的人向T建容量1的边。认识的人互相建容量1的边。

      这样求出最小割后,与S相连的点集表示最终选1的人,与T相连表示选0,每条割边表示一个冲突。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long
    #define N 305
    using namespace std;
    int n,m,S,T,tot,hd[N],d[N],vis[N],cur[N];
    struct edge{int v,next,cap,flow;}e[N*N*4];
    void adde(int u,int v,int c){
        e[tot].v=v;
        e[tot].next=hd[u];
        e[tot].cap=c;
        e[tot].flow=0;
        hd[u]=tot++;
    }
    
    bool bfs(){
        queue<int>q;
        memset(vis,0,sizeof(vis));
        q.push(S);d[S]=0;
        while(!q.empty()){
            int u=q.front();q.pop();vis[u]=1;
            for(int i=hd[u];~i;i=e[i].next){
                int v=e[i].v;
                if(e[i].cap<=e[i].flow||vis[v])continue;
                d[v]=d[u]+1;q.push(v);
            }
        }
        return vis[T];
    }
    
    int dfs(int u,int a){
        if(u==T||!a)return a;
        int fl=0,f;
        for(int i=hd[u];~i;i=e[i].next){
            int v=e[i].v;
            if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
                fl+=f;a-=f;
                e[i].flow+=f;
                e[i^1].flow-=f;
                if(a<=0)break;
            }
        }
        return fl;
    }
    int main(){
        scanf("%d%d",&n,&m);
        memset(hd,-1,sizeof(hd));
        S=0;T=n+1;
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            if(x)adde(S,i,1),adde(i,S,0);
            else adde(i,T,1),adde(T,i,0);
        }
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            adde(a,b,1);adde(b,a,1);
        }
        int flow=0;
        while(bfs()){
            for(int i=S;i<=T;i++)cur[i]=hd[i];
            flow+=dfs(S,0x3f3f3f3f);
        }
        printf("%d",flow);
        return 0;
    }
    

      

  • 相关阅读:
    中国跨境电商物流难题的三大解决方案
    美团外卖实时数仓建设实践
    美团商品知识图谱的构建及应用
    c++动态创建二维数组
    小鱼儿fish C#获取数组大小
    C#中定义数组--字符串及数组操作
    warning LNK4070的解决办法
    C++ 中 ZeroMemory、memset 危险需慎用
    C++中new和delete来创建和释放动态数组
    VS调试时查看动态数组的全部元素
  • 原文地址:https://www.cnblogs.com/wsy01/p/7932137.html
Copyright © 2011-2022 走看看