• Luogu P2057 [SHOI2007]善意的投票|最小割


    Luogu P2057 [SHOI2007]善意的投票|最小割

    重题:

    • [SPOJ1693]Coconuts
    • [JLOI2010]冠军调查

    题意:有(n)个小朋友投票,只有$0 1 $两种选择。每个人都有自己的主见,为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。求冲突数最小是多少?

    题解:

    又是一道神奇的网络流题。苦思冥想几天都不会。一看题解恍然大悟系列

    考虑最小割,将选(0)和选(1)的分两边,一边连源,一边连汇。再将朋友间连边(注意,所有朋友都要连,而不是连不同选择的(尝试了一下,貌似只连不同选择的能过?欢迎举反例),应连双向边),做最小割。

    根据“最大流=最小割”定理,做最大流即可解决。

    这样连边的意义?

    每条边的流量代表改变的代价

    具体来讲,源、汇的连边意味着与其意愿相反的代价,中间代表协商的代价

    那么,割掉就代表,与其意愿相反的代价和协商的代价的最小花费

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int cc,to[300000],net[300000],fr[300000],l[300000],fx[300000];
    int n,m,u,v,x,f[300000],q[300000];bool vis[300000];
    void addedge(int u,int v,int len)
    {
    	cc++;
    	to[cc]=v;net[cc]=fr[u];fr[u]=cc;l[cc]=len;fx[cc]=cc+1;
    	cc++;
    	to[cc]=u;net[cc]=fr[v];fr[v]=cc;l[cc]=0;fx[cc]=cc-1;
    }
    bool bfs()
    {
    	for (int i=1;i<=n+2;i++)
    	{
    		f[i]=2147483647;vis[i]=false;
    	}
    	f[n+1]=0;vis[n+1]=true;q[0]=n+1;
    	int h=0,t=0;
    	while (h<=t)
    	{
    		for (int i=fr[q[h]];i;i=net[i])
    		{
    			if (vis[to[i]]||!l[i]) continue;
    			f[to[i]]=f[q[h]]+1;q[++t]=to[i];
    			vis[to[i]]=true;
    			if (to[i]==n+2) return true;
    		}
    		h++;
    	}
    	return vis[n+2];
    }
    int dfs(int x,int y)
    {
    	if (x==n+2) return y; 
    	int now=0;
    	for (int i=fr[x];i;i=net[i])
    	{
    		if (f[to[i]]!=f[x]+1||!l[i]) continue;
    		int temp=dfs(to[i],min(y,l[i]));
    		if (temp) 
    		{
    			y-=temp;
    			l[i]-=temp;
    			l[fx[i]]+=temp;
    			now+=temp;
    		}
    		if (!y) return now;
    	}
    	return now;
    }
    int max_flow()
    {
    	int ans=0;
    	while (bfs())
    	{
    		ans+=dfs(n+1,2147483647);
    	}
    	return ans;
    }
    int main()
    {
    	cin>>n>>m;
    	for (int i=1;i<=n;i++)
    	{
    		cin>>x;
    		if (x) addedge(n+1,i,1);else addedge(i,n+2,1);
    	}
    	for (int i=1;i<=m;i++)
    	{
    		cin>>u>>v;
    		addedge(u,v,1);
    		addedge(v,u,1);
    	}
    	cout<<max_flow();
    	return 0;
    }
    

    广告:欢迎(hack)

    Test 1

    Test 2

    题解参考Solution in Luogu

  • 相关阅读:
    LTPA Cookie原理
    如何对更改internet密码所需的缓存时间进行调整?
    Freemem eclipse查看内存的小插件
    Java中static、final用法小结
    MANIFEST.MF内容属性名详细解释
    Java程序员的良药:应用程序的开发技巧
    spring struts2 ibatis框架整合开发
    java中静态代码块的用法 static用法详解 类的加载顺序
    从svn上直接导入项目到workspace中
    Eclipse自动生成UML图 Green UML和ModelGoon(直接推拽)
  • 原文地址:https://www.cnblogs.com/fmj123/p/Luogu2057.html
Copyright © 2020-2023  润新知