URAL 1736 Chinese Hockey 网络流+建图

题目链接:点击打开链接

题意:

给定n个队伍的得分情况,输出任意一个可行解。

n个队伍任意2个队伍 a, b 间有且仅有一场比赛。

比赛结果分4种:

1、a +3, b +0

2、a +0, b +3

3、a +2, b +1

4、a +1, b +2

我们发现其实每种结果2个队伍得分和总是3 且4种情况就是3的所有拆分和的形式。

所以我们把任意两个队伍组合成一个点。

把n个点连向源点,流上限为该队伍的得分。

对于1,2两个队伍

1 -> 点(1,2) 连流上限为3的边

2 -> 点(1,2) 连流上限为3的边

点(1,2) 到汇点连流上限为3的边。

若满流则有解。

1,2两个队伍间的情况就看点(1,2)的流入情况。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int inf = (int)(1e9);
const int M = 200 + 2;
const int E = M * M * 6 + M * 3;
const int N = M * M + M + 5;
struct Edge {
	int from, to, cap, nex;
};

int head[N], egnum;
Edge eg[E];

int a[M], n, st, ed;
int id[M][M], rid[N], tot;
int win[M][M];

void add(int u, int v, int cap, int rw = 0) {
	Edge E = {u, v, cap, head[u]};
	eg[egnum] = E;
	head[u] = egnum++;

	Edge E2 = {v, u, rw, head[v]};
	eg[egnum] = E2;
	head[v] = egnum++;
}
int sign[N];
bool bfs(int from, int to) {
	memset(sign, -1, sizeof sign);
	sign[from] = 0;

	queue<int> q;
	q.push(from);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = head[u]; i != -1; i = eg[i].nex) {
			int v = eg[i].to;
			if (sign[v] == -1 && eg[i].cap) {
				sign[v] = sign[u] + 1;
				q.push(v);
				if (sign[to] != -1)
					return true;
			}
		}
	}
	return false;
}
int Stack[N], top, cur[N];
int dicnic(int from, int to) {
	int ans = 0;
	while (bfs(from, to)) {
		memcpy(cur, head, sizeof head);
		int u = from;
		top = 0;
		while (true) {
			if (u == to) {
				int flow = inf, loc;
				for (int i = 0; i < top; ++i)
					if (flow > eg[Stack[i]].cap) {
						flow = eg[Stack[i]].cap;
						loc = i;
					}
				for (int i = 0; i < top; ++i) {
					eg[Stack[i]].cap -= flow;
					eg[Stack[i] ^ 1].cap += flow;
				}
				ans += flow;
				top = loc;
				u = eg[Stack[top]].from;
			}
			for (int i = cur[u]; i != -1; cur[u] = i = eg[i].nex)
				if (eg[i].cap && (sign[u] + 1 == sign[eg[i].to]))
					break;
			if (cur[u] != -1) {
				Stack[top++] = cur[u];
				u = eg[cur[u]].to;
			} else {
				if (top == 0)
					break;
				sign[u] = -1;
				u = eg[Stack[--top]].from;
			}
		}
	}
	return ans;
}
void init() {
	memset(head, -1, sizeof head);
	egnum = 0;
}
void pu(int x) {
	if (x == 0) {
		putchar('<');
	} else if (x == 1) {
		putchar('>');
	} else if (x == 2) {
		putchar('>');
		putchar('=');
	} else {
		putchar('<');
		putchar('=');
	}
}
void work() {
	int sum = 0, u, v;
	for (int i = 0; i < n; ++i) {
		scanf("%d", &a[i]);
		sum += a[i];
	}
	tot = n;
	for (int i = 0; i < n; ++i)
		for (int j = i + 1; j < n; ++j) {
			id[i][j] = ++tot;
			rid[tot] = j;
		}
	st = ++tot;
	ed = ++tot;
	init();
	for (int i = 0; i < n; ++i)
		add(st, i, a[i]);
	for (int i = 0; i < n; ++i)
		for (int j = i + 1; j < n; ++j) {
			add(i, id[i][j], 3);
			add(j, id[i][j], 3);
			add(id[i][j], ed, 3);
		}
	int g = dicnic(st, ed);
	if (g != sum) {
		puts("INCORRECT");
	} else {
		memset(win, -1, sizeof win);
		puts("CORRECT");
		for (int i = 0; i < egnum; ++i) {
			if (eg[i].from < n && eg[i].to > n && eg[i].to < st) {
				u = eg[i].from;
				v = rid[eg[i].to];
				if (u == v)
					continue;
				if (u > v)
					std::swap(u, v);
				if (win[u][v] == -1) {
					if (eg[i].cap == 0) {
						win[u][v] = 1; //1 = win, 0 = los, 2 = little win, 3 = little los
					} else if (eg[i].cap == 1) {
						win[u][v] = 2;
					} else if (eg[i].cap == 2) {
						win[u][v] = 3;
					} else {
						win[u][v] = 0;
					}
				}
			}
		}
		for (int i = 0; i < n; ++i)
			for (int j = i + 1; j < n; ++j) {
				printf("%d ", i + 1);
				pu(win[i][j]);
				printf(" %d\n", j + 1);
			}
	}
}
int main() {
	while (~scanf("%d", &n))
		work();
	return 0;
}
时间: 2024-10-06 18:44:17

URAL 1736 Chinese Hockey 网络流+建图的相关文章

HDU 4888 Redraw Beautiful Drawings 网络流 建图

题意: 给定n, m, k 下面n个整数 a[n] 下面m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵,若有多解输出Not Unique,若无解输出Impossible 思路:网络流,,, n行当成n个点,m列当成m个点 从行-列连一条流量为k的边,然后源点-行连一条a[i]的边, 列-汇点 流量为b[i] 瞎了,该退役了 T^T #include<stdio.h> #include<string.h> #include<iostream&

网络流建图/模型总结

网络流真的是一个什么强大的算法啦.令人头疼的是网络流的灵活应用之广泛,网络流的题目建图方式也是千奇百怪,所以蒟蒻打算总结一下网络流的建图方式.秉着不重复造轮子的原则(其实是博主又菜又想找个借口),网上大佬写的好的就直接贴网址了. (更新ing) 大佬强无敌的总结:https://www.cnblogs.com/victorique/p/8560656.html#autoid-1-10-3 最小割应用:https://wenku.baidu.com/view/87ecda38376baf1ffc4

[ZJOI2010]贪吃的老鼠(网络流+建图)

题目描述 奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉.第j只老鼠吃奶酪的速度为sj,因此如果它单独吃完第i快奶酪所需的时间为pi/sj.老鼠们吃奶酪的习惯很独特,具体来说: (1) 在任一时刻,一只老鼠最多可以吃一块奶酪: (2) 在任一时刻,一块奶酪最多被一只老鼠吃. 由于奶酪的保质期常常很短,为了将它们全部吃掉,老鼠们需要使用一种神奇的魔法来延长奶酪的保质期.

hdu-4292.food(类dining网络流建图)

Food Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9289    Accepted Submission(s): 3019 Problem Description You, a part-time dining service worker in your college’s dining hall, are now confus

UVA 10779 Collectors Problem 网络流+建图

题目链接:点击打开链接 题意:白书P370 思路: 因为问的是最后贴纸总数,那么就设最后的贴纸总数是网络流的答案. 首先我们模拟贴纸的流动过程: Bob 的 某种贴纸a -> 给一个没有a贴纸的人Peo -> 还给Bob一个Peo的某张重复贴纸 -> 这张贴纸可以算作答案了 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include

网络流建图

最大流问题变形:多汇点多源点:加一个超级源点S与超级汇点TS到每个源点建立一条容量为对应的最大流出容量的边每个汇点到T建立一条容量为对应的最大流入容量的边无向图:把无向图的一条边拆成两个反向的容量相等的有向边顶点上有流量限制:把每个顶点拆成两个顶点,一个入,一个出,然后入->出连接一条容量为顶点流量限制c的边有最小流量限制:最小费用流问题变形:与最大流类似 最小权匹配问题:两类物体之间的对应关系,把两类物体看成顶点,并在顶点之间连接权重为对应花费的边,就转化为最小权匹配问题.可以使用最小费用流解

[SDOI2010] 所驼门王的宝藏 [建图+tarjan缩点+DAG dp]

题面传送门: 传送门 思路: 看完题建模,容易得出是求单向图最长路径的问题 那么把这张图缩强联通分量,再在DAG上面DP即可 然而 这道题的建图实际上才是真正的考点 如果对于每一个点都直接连边到它所有的后继节点,那么可以被卡掉(1e5个点在同一行上) 考虑改变思路,运用网络流建图中的一个常用技巧:把横边和竖边映射成点,再从每个点向所在横坐标.纵坐标代表的点连边即可 这样会有2e6+1e5个点,但是tarjan算法效率O(n),完全无压力 自由(和谐)门的话,目前还没有比较好的方法解决 上网看了一

POJ 1149 网络流 合并建图

这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独建点,猪圈无非就是向顾客输送流量 以及向同时开着的猪圈输送流量,这一步可以直接缩为,当某个猪圈被第一次打开,它里面的流量就全部输送给那个顾客那个点,而且可以叠加,因为每一次猪圈是可以互通的,而且猪圈本身是没有容量限制,如果有限制,那就还得再考虑. 此外,每次对猪圈的接下来的访问者都进行建边.用来输送

HDU 3036 Escape 网格图多人逃生 网络流||二分匹配 建图技巧

前言 在编程过程中总结归纳出来的一种编程经验,从而形成的设计思想称为设计模式. 设计模式有23种.它适用于所有的编程语言. 常用的有创新型的设计模式:简单工厂.抽象工厂和单例模式:行为型的设计模式:模板设计模式.观察者模式和命令模式:结构性的设计模式:适配器设计模式.代理模式(静态和动态两种,典型的有在spring的AOP编程中使用)和装饰器设计模式. 正文 单例模式(singleton) 保证一个类在内存中只能创建一个实例. 1.实现步骤: 1)将构造器私有化,即使用private修饰构造器