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

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连同意的,T连不同意的

然后朋友相互连接

代码:

#include<cstdio>
 #include<cstring>
 #include<queue>
 #include<cmath>
 using namespace std;
 const int Ni = 100210;
 const int MAX = 1<<26;
 struct Edge{
     int u,v,c;
     int next;
 }edge[20*Ni];
 int n,m;
 int edn;//边数
 int p[Ni];//父亲
 int d[Ni];
 int sp,tp;//原点,汇点

 void addedge(int u,int v,int c)
 {
     edge[edn].u=u; edge[edn].v=v; edge[edn].c=c;
     edge[edn].next=p[u]; p[u]=edn++;

     edge[edn].u=v; edge[edn].v=u; edge[edn].c=0;
     edge[edn].next=p[v]; p[v]=edn++;
 }
 int bfs()
 {
     queue <int> q;
     memset(d,-1,sizeof(d));
     d[sp]=0;
     q.push(sp);
     while(!q.empty())
     {
         int cur=q.front();
         q.pop();
         for(int i=p[cur];i!=-1;i=edge[i].next)
         {
             int u=edge[i].v;
             if(d[u]==-1 && edge[i].c>0)
             {
                 d[u]=d[cur]+1;
                 q.push(u);
             }
         }
     }
     return d[tp] != -1;
 }
 int dfs(int a,int b)
 {
     int r=0;
     if(a==tp)return b;
     for(int i=p[a];i!=-1 && r<b;i=edge[i].next)
     {
         int u=edge[i].v;
         if(edge[i].c>0 && d[u]==d[a]+1)
         {
             int x=min(edge[i].c,b-r);
             x=dfs(u,x);
             r+=x;
             edge[i].c-=x;
             edge[i^1].c+=x;
         }
     }
     if(!r)d[a]=-2;
     return r;
 }

 int dinic(int sp,int tp)
 {
     int total=0,t;
     while(bfs())
     {
         while(t=dfs(sp,MAX))
         total+=t;
     }
     return total;
 }
 int main()
 {
     int i,u,v,c;
     while(~scanf("%d%d",&n,&m))
     {
         edn=0;//初始化
         memset(p,-1,sizeof(p));
         sp=0;tp=n+1;
         for(int i=1;i<=n;i++)
         {
             int x;
             scanf("%d",&x);
             if(x)addedge(sp,i,1);
             else addedge(i,tp,1);
         }
         for(int i=1;i<=m;i++)
         {
             int x,y;
             scanf("%d%d",&x,&y);
             addedge(x,y,1);
             addedge(y,x,1);
         }
         printf("%d\n",dinic(sp,tp));
     }
     return 0;
 }
时间: 2024-10-11 12:56:11

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

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

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1934 [题目大意] 每个人对于投票都有自己原来的观点:1或者0, 他可以违背自己原来的意愿投相反的票, 同时存在一些相互的朋友关系, 我们定义一次投票的冲突数为好朋友之间发生冲突的总数, 加上和所有和自己本来意愿发生冲突的人数. 求最小冲突. [题解] 我们将好友之间连双向边,流量为1,对于原本意愿为1的连源点,0的连汇点,流量为1, 该图最小割即为最小冲突. [代码] #inclu

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