zoukankan      html  css  js  c++  java
  • BZOJ 1934善意的投票(最小割) Iscream

    1934: [Shoi2007]Vote 善意的投票

    Time Limit: 1 Sec  Memory Limit: 64 MB
    Submit: 2354  Solved: 1471
    [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

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

     

    题目链接:

        http://www.lydsy.com/JudgeOnline/problem.php?id=1934 

    Solution

        小朋友的冲突就是割,然后这道题要求的就是最小的割。。。

        从源点向刚开始为1的点连边,从每个刚开始为0的点向汇点连边,每条边容量为1。。。

        然后每一对好朋友之间加一条双向边,容量为1。。。

        都是套路。。。都是套路。。。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #define inf 1000000000
    #define N 10000
    using namespace std;
    inline int Read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    char ch;
    int n,m,S,T,ans;
    int cnt=1;
    int hed[N],h[N],q[N];
    struct edge{
        int r,nxt,v;
    }e[300000];
    void insert(int u,int v,int w){
        e[++cnt].r=v;e[cnt].nxt=hed[u];hed[u]=cnt;e[cnt].v=w;
    }
    bool bfs(){
        int head=0,tail=1,now;
        memset(h,-1,sizeof(h));
        h[S]=1;q[1]=S;
        while(head!=tail){
            head++;now=q[head];
            for(int i=hed[now];i;i=e[i].nxt)
                if(e[i].v&&h[e[i].r]==-1){
                    h[e[i].r]=h[now]+1;
                    q[++tail]=e[i].r;
                }
        }
        return h[T]!=-1;
    }
    int dfs(int x,int F){
        if(x==T) return F;
        int w,used=0;
        for(int i=hed[x];i;i=e[i].nxt)
            if(h[x]+1==h[e[i].r]){
                w=F-used;
                w=dfs(e[i].r,min(w,e[i].v));
                e[i].v-=w;
                e[i^1].v+=w;
                used+=w;
                if(used==F) return F;
            }
        if(!used) h[x]=-1;
        return used;
    }
    void dinic(){
        while( bfs() )
            ans+=dfs(0,inf);
    }
    int main(){
    	int sum=0;
    	int u,v,w;
        n=Read();m=Read();
        S=0;T=n+1;
        for(int i=1;i<=n;i++){
        	w=Read();
        	if(w){
        		insert(S,i,1);
        		insert(i,S,0);
    		}
        	else{
        		insert(i,T,1);
        		insert(T,i,0);
    		}
    	}
    	for(int i=1;i<=m;i++){
    		u=Read();v=Read();
    		insert(u,v,1);
    		insert(v,u,1);
    	}
        dinic();
        printf("%d\n",ans);
        return 0;
    }
    

      

      

    This passage is made by Iscream-2001.

  • 相关阅读:
    python输出shell命令执行结果
    python实验二:字符串排序
    python学习系列
    linux命令系列目录
    git初步
    HTML基础教程 七 高级
    HTML/CSS基础教程 六
    linux命令---sed
    linux命令---unzip
    模块
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/7746328.html
Copyright © 2011-2022 走看看