bzoj1934

幼儿园里有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

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

这是到网络流的例题吧。

题解:就是每个小朋友可以从投自己心仪的票,然后没有好朋友,这样就是互相不冲突的,

有冲突的话就是要么符合好朋友,要么就是符合自己的心仪投票,没有其他的方案了,

  这样如果小朋友要符合好朋友,违背心向,则让其连向好朋友,表示他的意向变为好朋友的,

  然后他就违背了自己的心愿,就是+1的结果,也或者是,将好朋友的变成了自己的票,然后去

  一个最小的,就是最小割。使图没有冲突。

  然后就是跑一次网络流。

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 using namespace std;
  7
  8 const int INF=1e8+8;
  9
 10 int n,m,S,T;
 11 int cnt,head[507],next[101007],val[101007],rea[101007];
 12 int dis[507],p[507];//因为是宽搜,所以p的空间开节点个数
 13
 14 void add(int u,int v,int zhi)
 15 {
 16     cnt++;
 17     next[cnt]=head[u];
 18     head[u]=cnt;
 19     rea[cnt]=v;
 20     val[cnt]=zhi;
 21 }
 22 bool bfs()
 23 {
 24     memset(dis,-1,sizeof(dis));
 25     dis[S]=0;
 26     int hd=0,tl=1;
 27     p[tl]=S;
 28     while (hd<tl)
 29     {
 30         hd++;
 31         int u=p[hd];
 32         for (int i=head[u];i!=-1;i=next[i])
 33         {
 34             int v=rea[i],cost=val[i];
 35             if (dis[v]==-1&&cost>0)//如果当前阻塞流的流量为0,则不必要到达
 36             {
 37                 dis[v]=dis[u]+1;
 38                 if (v==T) return 1;//到达终点即可
 39                 p[++tl]=v;
 40             }
 41         }
 42     }
 43     return 0;
 44 }
 45 int dfs(int u,int MM)
 46 {
 47     if (!MM||u==T) return MM;
 48     int res=0;
 49     for (int i=head[u];i!=-1;i=next[i])
 50     {
 51         int v=rea[i],cost=val[i];
 52         if (dis[v]!=dis[u]+1) continue;//严格按照层次来进行
 53         int x=dfs(v,min(MM,cost));
 54         if (x)
 55         {
 56             val[i]-=x,val[i^1]+=x;
 57             MM-=x,res+=x;
 58             if (!MM) break;//当前弧优化
 59         }
 60     }
 61     if (MM==-1) dis[u]=-1;
 62     return res;
 63 }
 64 int dinic()
 65 {
 66     int res=0;
 67     while (bfs())//构造层次图,一旦无法到达终点,则增广结束,已经求得了最大流
 68     {
 69         int x=dfs(S,INF);//多路增广,每次初始为最大的流量
 70         while (x)
 71         {
 72             res+=x;
 73             x=dfs(S,INF);
 74         }
 75     }
 76     return res;
 77 }
 78 int main()
 79 {
 80     while (~scanf("%d%d",&n,&m))
 81     {
 82         cnt=1;//这是一个技巧,对反向边的构造有帮助
 83         memset(head,-1,sizeof(head));
 84         S=n+1;
 85         T=n+2;
 86         int x,y;
 87         for (int i=1;i<=n;i++)
 88         {
 89             scanf("%d",&x);
 90             if (x==1) add(S,i,1),add(i,S,0);
 91             else add(i,T,1),add(T,S,0);
 92         }
 93         for (int i=1;i<=m;i++)
 94         {
 95             scanf("%d%d",&x,&y);
 96             add(x,y,1),add(y,x,1);
 97         }
 98         printf("%d\n",dinic());
 99     }
100 }
时间: 2024-11-17 20:04:07

bzoj1934的相关文章

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

bzoj1934&amp;bzoj2768:最小割

果然智商是硬伤...去掉最少的边使图不联通,不联通意味着不会还存在朋友之间有矛盾,那么去掉的边有两种可能,1是与st相连的(Orz就是这里忽略了),那么就是违心说话的人,另外就是中间的边,那么就是朋友之间立场不同的人.然后跑一下最大流就好了. ------------------------------------------------------------------------------------------- #include<cstdio> #include<cstrin

BZOJ1934:[SHOI2007]善意的投票 &amp; BZOJ2768:[JLOI2010]冠军调查——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=1934 https://www.lydsy.com/JudgeOnline/problem.php?id=2768 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票.我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲

[bzoj1934]善意的投票

最小割,考虑最小割就是要将整张图分为两块,本题中就分别表示赞同和不赞同,那么首先一开始赞同的点向S连边,不赞同的点向T连边,如果这些点分到了另一边就要割掉这条边,朋友关系同理,连双向边同样表示分到两边要割掉这条边,跑最小割=最大流即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 305 4 struct ji{ 5 int nex,to,len; 6 }edge[N*N]; 7 queue<int>q;

二分图&amp;网络流&amp;最小割等问题的总结

二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 带下界网络流 最小割问题的总结: *意义 1.加inf的边表示不能被割,通常用于体现某个点必须属于某个集合 连边(s,u,w)代表如果u不在s割的话需要付出代价w 2.连边(u,v,w)代表如果u在s割,v在t割需要付出代价w 但注意,如果u在t割,v在s割是不需要付出代价的. 那么如果连边(u,v,w)以及(v,u,w)则说明当u与v所属割不同的时候需要付出代价w *

bzoj网络流

近期看了一些bzoj的网络流,深感智商不够.不过对于网络流又有了进一步的理解. 还是mark一下吧. 献上几篇论文:1)<最小割模型在信息学竞赛中的应用> 2)<浅析一类最小割问题> 1.bzoj1066(最大流) 题意:戳这里 思路:很明显拆点最大流模型,然后对于每个点每个高度流量限为1,那么根据最大流即为可以出去的蜥蜴的数量. 2.bzoj1077(费用流) 戳这里 3.bzoj1391(最小割) 题意:戳这里 思路:有点像最大权闭合图..可以利用最小割的性质建图: <S

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

网络流专题练习Day2

04/17  目前做了:4题 由于目前四道都是1A感觉非常爽... BZOJ1412: [ZJOI2009]狼和羊的故事 “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆.可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已.所以Orez决定在羊狼圈中再加入一

20160529~20160604 13

蒟蒻Yzm 20160530 bzoj2333 http://www.lydsy.com/JudgeOnline/problem.php?id=2333 题意: 有N个节点,M个操作:连接两个节点.单个节点的权值增加v.节点所在的连通块的所有节点的权值增加v.所有节点的权值增加v.询问节点当前的权值.询问节点所在的连通块中权值最大的节点的权值.询问所有节点中权值最大的节点的权值. N,M≤300000 代码: 1 #include <cstdio> 2 #include <cstring