BZOJ 1934 [Shoi2007]Vote 善意的投票(最小割)

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1934

【题目大意】

  每个人对于投票都有自己原来的观点:1或者0,
  他可以违背自己原来的意愿投相反的票,
  同时存在一些相互的朋友关系,
  我们定义一次投票的冲突数为好朋友之间发生冲突的总数,
  加上和所有和自己本来意愿发生冲突的人数。
  求最小冲突。

【题解】

  我们将好友之间连双向边,流量为1,对于原本意愿为1的连源点,0的连汇点,流量为1,
  该图最小割即为最小冲突。

【代码】

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX_V=20010;
struct edge{int to,cap,rev;};
vector<edge> G[MAX_V];
int level[MAX_V],iter[MAX_V];
void add_edge(int from,int to,int cap){
    G[from].push_back((edge){to,cap,G[to].size()});
    G[to].push_back((edge){from,0,G[from].size()-1});
}
void bfs(int s){
    memset(level,-1,sizeof(level));
    queue<int> que;
    level[s]=0;
    que.push(s);
    while(!que.empty()){
        int v=que.front(); que.pop();
        for(int i=0;i<G[v].size();i++){
            edge &e=G[v][i];
            if(e.cap>0&&level[e.to]<0){
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f){
    if(v==t)return f;
    for(int &i=iter[v];i<G[v].size();i++){
        edge &e=G[v][i];
        if(e.cap>0&&level[v]<level[e.to]){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }return 0;
}
int max_flow(int s,int t){
    int flow=0;
    for(;;){
        bfs(s);
        if(level[t]<0)return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,INF))>0){
            flow+=f;
        }
    }
}
int n,m;
int main(){
    while(~scanf("%d%d",&n,&m)){
        int s=n+1,t=s+1;
        for(int i=0;i<=t;i++)G[i].clear();
        for(int i=1;i<=n;i++){
            int x; scanf("%d",&x);
            if(x)add_edge(s,i,1);
            else add_edge(i,t,1);
        }
        for(int i=1;i<=m;i++){
            int x,y; scanf("%d%d",&x,&y);
            add_edge(x,y,1);
            add_edge(y,x,1);
        }printf("%d\n",max_flow(s,t));
    }return 0;
}
时间: 2024-08-05 23:41:29

BZOJ 1934 [Shoi2007]Vote 善意的投票(最小割)的相关文章

BZOJ 1934: [Shoi2007]Vote 善意的投票 最小割

1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1934 Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票.我们定义一次投票的冲突数

BZOJ 1934 [Shoi2007]Vote 善意的投票

我大概是把自己水废掉了. 第一眼匈牙利?不知道怎么想到的,然后发现不可做. 似乎是网络流呀. 看了半天硬是没把图建出来. 出去冷静一下. wc这不是和文理分科那啥一模一样嘛,还简单得多... 我是zz,鉴定完毕. //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring

1934: [Shoi2007]Vote 善意的投票

1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 1174  Solved: 723[Submit][Status] Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票.我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所

【BZOJ】1934: [Shoi2007]Vote 善意的投票(网络流/-二分图匹配)

一开始我想到了这是求最小割,但是我认为这题二分图可做,将1的放在左边,0的放在右边,然后朋友连边,如果有冲突就相当于有1条x-y的边,求最小割也就是最大匹配即可..可是不知道为什么就错了. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using names

【BZOJ 1934】 [Shoi2007]Vote 善意的投票

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

BZOJ 1934 善意的投票(最小割)

把人分成两个集合,一个赞成睡觉,一个反对睡觉.好朋友连一条容量为1的双向边,s向赞成睡觉的连边,反对睡觉的向t连边. 那么这个图的一个割就对应着一个方案.如果割掉s和v的边,就代表v投意见与它自己相反的票,t和v的边同理.割掉u和v的边,就代表了这对好朋友之间意见不同. 这样求出一个割之后,好朋友之间意见不同的边都被割去了. 求出此图的最小割即为答案. # include <cstdio> # include <cstring> # include <cstdlib>

bzoj1934: [Shoi2007]Vote 善意的投票

一定要想到是最小割. 虚拟源点S连支持者容量为1,反对者连虚拟汇点容量为1,支持者连反对者容量为1. 割俩面的点,一面是支持,一面是反对,冲突数就是割(哥..雾). 最小冲突数就是最小割. #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int maxn = 300 + 10; const int maxm = 100000 + 10; const int

【BZOJ】【1934】【SHOI 2007】Vote 善意的投票

网络流/最小割 简单题= =直接利用最小割的性质: 割掉这些边后,将所有点分成了两部分(两个连通块),我们可以假定与S相连的是投赞成票,与T相连的是投反对票. 那么如果一个小朋友原本意愿是睡觉,那么连边 S->i ,边权为1,表示如果割掉这条边(即让他投违反意愿的票)则冲突数+1.原本意愿是不睡觉的连 i->T,边权为1,意义同理. 然后处理“好朋友”的情况,对每对好朋友,连边 i->j 和 j->i,边权均为1,表示如果割掉这条边(则两个点所属不同块)则冲突数+1. 要求总冲突数

BZOJ 1266 AHOI 2006 上学路线route 最小割

题目大意:给出一个无向图,问从1到n的最短路发生变化需要割掉最少花费的边权总值是多少. 思路:先要把所有最短路上的边搞出来,一个Floyd就可以解决,然后把所有在最短路上的边都加到最大流的图中,然后跑最小割就是答案. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 510