zoukankan      html  css  js  c++  java
  • 【洛谷P2057】善意的投票 / 冠军调查

    题目

    题目链接:https://www.luogu.com.cn/problem/P2057
    幼儿园里有 \(n\) 个小朋友打算通过投票来决定睡不睡午觉。

    对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。

    虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。

    我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。

    我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

    思路

    第一道完全自己想的一次过的网络流题 /fad。
    我们从源点 \(S\) 向投 \(1\) 的人连一条流量为 \(1\) 的边,从投 \(0\) 的人向汇点 \(T\) 连一条流量为 \(1\) 的边。
    然后对于一对朋友 \(u,v\),如果他们投票相同,那么互相连一条流量为 \(1\) 的边,否则从投 \(1\) 的人向投 \(0\) 的人连一条流量为 \(1\) 的边。
    这样我们就保证了如果存在一条路径 \(S\to x\to y\to T\),割 \(x\to y\) 相当于 \(x\)\(y\) 都不改票;割 \(S\to x\)\(y\to T\) 都相当于改变选票,但是改变选票的人的其他好友依然可以有流量流向他,所以还是需要断掉其他边。
    此时这张图的最小割就是答案。跑最大流即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=310,M=N*N*4,Inf=1e9;
    int n,m,S,T,maxf,tot=1,head[N],a[N],cur[N],dep[N];
    
    struct edge
    {
    	int next,to,flow;
    }e[M];
    
    void add(int from,int to,int flow)
    {
    	e[++tot].to=to;
    	e[tot].flow=flow;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    bool bfs()
    {
    	memcpy(cur,head,sizeof(cur));
    	memset(dep,0x3f3f3f3f,sizeof(dep));
    	queue<int> q; q.push(S);
    	dep[S]=1;
    	while (q.size())
    	{
    		int u=q.front(); q.pop();
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			int v=e[i].to;
    			if (e[i].flow && dep[v]>dep[u]+1)
    			{
    				dep[v]=dep[u]+1;
    				q.push(v);
    			}
    		}
    	}
    	return dep[T]<Inf;
    }
    
    int dfs(int x,int flow)
    {
    	if (x==T)
    	{
    		maxf+=flow;
    		return flow;
    	}
    	int used=0,ret;
    	for (int i=cur[x];~i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if (e[i].flow && dep[v]==dep[x]+1)
    		{
    			ret=dfs(v,min(flow-used,e[i].flow));
    			e[i].flow-=ret; e[i^1].flow+=ret;
    			used+=ret;
    			if (used==flow) return flow;
    		}
    	}
    	return used;
    }
    
    void dinic()
    {
    	while (bfs())
    		dfs(S,Inf);
    }
    
    int main()
    {
    	S=N-1; T=N-2;
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		if (a[i]) add(S,i,1),add(i,S,0);
    			else add(i,T,1),add(T,i,0);
    	}
    	for (int i=1,x,y;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		if (a[y]==1) swap(x,y);
    		if (a[x]==a[y]) add(x,y,1),add(y,x,1);
    			else add(x,y,1),add(y,x,0);
    	}
    	dinic();
    	printf("%d",maxf);
    	return 0;
    }
    
  • 相关阅读:
    Spring boot项目搭建及简单实例
    nodejs的web开发框架之express(其中项目的案例也是后端渲染)
    node的系统核心模块实现服务器功能、用nodejs做动态网站(后端渲染)
    nodejs包管理工具npm 、yarn
    node的基本操作、文件路径、文件读、取、目录读取删
    了解node、ES6
    相对单位em、rem
    响应式开发---网页的布局方式、媒体查询、栅格化布局、less语言
    移动端插件的使用---zepto、iScroll、swiper、swipe、fastclick
    base.css
  • 原文地址:https://www.cnblogs.com/stoorz/p/13790049.html
Copyright © 2011-2022 走看看