• BZOJ1934【SHOI2007】善意的投票 <网络流>


    善意的投票

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

    输入输出格式
    输入格式:
    文件的第一行只有两个整数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不会重复。
    输出格式:
    只需要输出一个整数,即可能的最小冲突数。

    输入输出样例
    输入样例:
    3 3
    1 0 0
    1 2
    1 3
    3 2
    输出样例:
    1

    说明
    2≤n≤300,1≤m≤n(n-1)/2。

    标签:网络流,最小割

    最小割见图如下:
    如果本人意见为0,则与源点相连,反之与汇点相连。
    对于每对朋友关系,互相连边。
    所有边的容量均为1,跑最大流最小割即可。

    原理:对于每个人,如果有朋友与他意见不合,则他要么割自己到源点(汇点)的一条边,要么割与朋友的边,代价等于容量。

    附上AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define MAX_N 300
    #define MAX_M MAX_N*(MAX_N-1)*2 
    #define INF 2147483647
    using namespace std;
    int n, m, s, t;
    int d[MAX_N+5], first[MAX_N+5], cnt;
    struct node {int v, c, next;} E[MAX_M+5];
    void Init() {
    	cnt = 0;
    	memset(first, -1, sizeof(first));
    }
    void Insert(int u, int v, int c) {
    	E[cnt].v = v, E[cnt].c = c;
    	E[cnt].next = first[u];
    	first[u] = cnt++;
    }
    void AddEdge(int u, int v, int c) {
    	Insert(u, v, c);
    	Insert(v, u, 0);
    }
    bool BFS() {
    	memset(d, -1, sizeof(d));
    	queue <int> que;
    	que.push(s), d[s] = 0;
    	while (!que.empty()) {
    		int u = que.front();
    		for (int i = first[u]; i != -1; i = E[i].next) {
    			int v = E[i].v;
    			if (E[i].c && d[v] == -1) {
    				d[v] = d[u]+1;
    				que.push(v);
    			}
    		}
    		que.pop();
    	}
    	return (d[t] != -1);
    }
    int DFS(int u, int flow) {
    	if (u == t)	return flow;
    	int ret = 0;
    	for (int i = first[u]; i != -1; i = E[i].next) {
    		int v = E[i].v;
    		if (E[i].c && d[v] == d[u]+1) {
    			int tmp = DFS(v, min(flow, E[i].c));
    			if (!tmp)	continue;
    			flow -= tmp, E[i].c -= tmp;
    			ret += tmp, E[i^1].c += tmp;
    			if (!flow)	break;
    		}
    	}
    	if (!ret)	d[u] = -1;
    	return ret;
    }
    int Dinic() {
    	int ret = 0;
    	while (BFS())
    		ret += DFS(s, INF);
    	return ret;
    }
    int main() {
    	Init();	scanf("%d%d", &n, &m);
    	s = 0, t = n+1;
    	for (int i = 1; i <= n; i++) {
    		int f;	scanf("%d", &f);
    		if (f == 1) {
    			AddEdge(s, i, 1);
    		} else {
    			AddEdge(i, t, 1);
    		}
    	}
    	for (int i = 0; i < m; i++) {
    		int u, v;	scanf("%d%d", &u, &v);
    		AddEdge(u, v, 1);
    		AddEdge(v, u, 1);
    	}
    	printf("%d", Dinic());
    	return 0;
    }
    
  • 相关阅读:
    发布 Rafy .NET Standard 版本 Nuget 包
    使用 MarkDown & DocFX 升级 Rafy 帮助文档
    apache2服务器支持cgi功能
    百兆网口与千兆网口速率协商不成功
    ubuntu etho0 up cron
    linux 后台进程
    MySQL的事务性
    linux下visual studio code配置c++调试环境实例
    linux下visual studio code中gdb调试文件launch.json解析
    Zookeeper安装后,编译C client时报错"syntax error near unexpected token `1.10.2"
  • 原文地址:https://www.cnblogs.com/AzraelDeath/p/7576365.html
Copyright © 2020-2023  润新知