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

网络流/最小割



  简单题= =直接利用最小割的性质:

    割掉这些边后,将所有点分成了两部分(两个连通块),我们可以假定与S相连的是投赞成票,与T相连的是投反对票。

  那么如果一个小朋友原本意愿是睡觉,那么连边 S->i ,边权为1,表示如果割掉这条边(即让他投违反意愿的票)则冲突数+1。原本意愿是不睡觉的连 i->T,边权为1,意义同理。

  然后处理“好朋友”的情况,对每对好朋友,连边 i->j 和 j->i,边权均为1,表示如果割掉这条边(则两个点所属不同块)则冲突数+1。

  要求总冲突数(割掉的边数)最小,所以最小割即为答案。

  (如果存在一条S->T的路径,那这个路径上的小朋友是投赞成呢还是反对呢?一定要表态的啊……所以必须割掉啊……)

  1 /**************************************************************
  2     Problem: 1934
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:16 ms
  7     Memory:4408 kb
  8 ****************************************************************/
  9
 10 //BZOJ 1934
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 inline int getint(){
 23     int v=0,sign=1; char ch=getchar();
 24     while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();}
 25     while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();}
 26     return v*sign;
 27 }
 28 const int N=320,M=200000,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31 int n,m;
 32 struct edge{
 33     int from,to,v;
 34 };
 35 inline int pack(int i,int j){return (i-1)*m+j;}
 36 struct Net{
 37     edge E[M];
 38     int head[N],next[M],cnt;
 39     void add(int x,int y,int v){
 40         E[++cnt]=(edge){x,y,v};
 41         next[cnt]=head[x]; head[x]=cnt;
 42         E[++cnt]=(edge){y,x,0};
 43         next[cnt]=head[y]; head[y]=cnt;
 44     }
 45     int s,t,cur[N],d[N],Q[N];
 46     void init(){
 47         n=getint();m=getint();
 48         cnt=1;
 49         s=0; t=n+1;
 50         F(i,1,n)
 51             if (getint()) add(s,i,1);
 52             else add(i,t,1);
 53         int x,y;
 54         F(i,1,m){
 55             x=getint(); y=getint();
 56             add(x,y,1);
 57             add(y,x,1);
 58         }
 59     }
 60     bool mklevel(){
 61         memset(d,-1,sizeof d);
 62         d[s]=0;
 63         int l=0,r=-1;
 64         Q[++r]=s;
 65         while(l<=r){
 66             int x=Q[l++];
 67             for(int i=head[x];i;i=next[i])
 68                 if (d[E[i].to]==-1 && E[i].v){
 69                     d[E[i].to]=d[x]+1;
 70                     Q[++r]=E[i].to;
 71                 }
 72         }
 73         return d[t]!=-1;
 74     }
 75     int dfs(int x,int a){
 76         if (x==t||a==0) return a;
 77         int flow=0;
 78         for(int &i=cur[x];i && flow<a;i=next[i])
 79             if (d[E[i].to]==d[x]+1 && E[i].v){
 80                 int f=dfs(E[i].to,min(a-flow,E[i].v));
 81                 E[i].v-=f;
 82                 E[i^1].v+=f;
 83                 flow+=f;
 84             }
 85         if (!flow) d[x]=-1;
 86         return flow;
 87     }
 88     int Dinic(){
 89         int flow=0;
 90         while(mklevel()){
 91             F(i,s,t) cur[i]=head[i];
 92             flow+=dfs(s,INF);
 93         }
 94         return flow;
 95     }
 96 }G1;
 97 int main(){
 98 #ifndef ONLINE_JUDGE
 99     freopen("1934.in","r",stdin);
100     freopen("1934.out","w",stdout);
101 #endif
102     G1.init();
103     printf("%d\n",G1.Dinic());
104     return 0;
105 }

时间: 2024-10-10 15:11:56

【BZOJ】【1934】【SHOI 2007】Vote 善意的投票的相关文章

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

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

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个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票.我们定义一次投票的冲突数

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 善意的投票(最小割)

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

【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 善意的投票

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

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 1935 SHOI 2007 Tree 园丁的烦恼 树状数组

题目大意:给出平面中的一些点,询问平面中的一些矩形中有多少点. 思路:正常应该是二维树状数组,然后数据范围太大.所以就只能按照一个坐标排序,另一个坐标跑树状数组.注意离线操作,一个问题拆成4个. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 500010 #define RANGE 10000010 using n

C++之路进阶——最大流(善意的投票)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 1646  Solved: 1006[