例题6-19 自组合(Self-Assembly, ACM/ICPC World Finals 2013, UVa 1572)

原题链接:https://vjudge.net/problem/UVA-1572
分类:图
备注:有向环图

跟着紫书的思路:

  • 除了"00"的边以外,将正方形的边看作是结点,去构成有向边。
  • 注意:要构成有向边是和其它正方形的边来构成而不是和自身的边构成(懂 得了这个之后真是意外的简单)。如正方形A+00A+B+,对于边A+来说,由于另外的边可用的有A+和B+,则通过它们可与A-,B-相连,于是构成A+ -> A-和A+ -> B-两条有向边。
  • 然后判断是否存在有向环,若存在则输出unbounded,否则输出bounded。下述代码用floyd来判断,速度比较慢。

代码如下:

#include<iostream>
#include<cstring>
#include<set>
#include<map>
using namespace std;
const int maxn = 52 + 5;
int n, cnt, g[maxn][maxn], hav[maxn];
map<string, int>id;
void update(int a, int b, int c, int d) {
	if (a == 0)return;
	int tmp[3] = { b,c,d };
	for (int i = 0; i < 3; i++) {
		if (tmp[i] == 0)continue;
		if (tmp[i] % 2)tmp[i]++;
		else tmp[i]--;
		g[a][tmp[i]] = 1;
	}
}
int main(void) {
	id["00"] = cnt++;
	for (char ch = 'A'; ch <= 'Z'; ch++) {//最大为52
		char tmp[3] = { ch,'+',NULL };
		string x = tmp;
		id[x] = cnt++;//2 * (ch - 'A') + 1
		x[1] = '-';
		id[x] = cnt++;//2 * (ch - 'A') + 2
	}
	while (cin >> n) {
		memset(g, 0, sizeof(g));
		memset(hav, 0, sizeof(hav));
		while (n--) {
			string x;
			int a[4];
			cin >> x;
			for (int i = 0; i < 4; i++) {
				a[i] = id[x.substr(2 * i, 2)];
				hav[a[i]] = 1;
			}
			for (int i = 0; i < 4; i++) 
				update(a[i], a[(i + 1) % 4], a[(i + 2) % 4], a[(i + 3) % 4]);
		}
		for (int k = 0; k < cnt; k++)
			for (int i = 0; i < cnt; i++)
				for (int j = 0; j < cnt; j++) {
					if (!hav[k] || !hav[i] || !hav[j])continue;
					g[i][j] = g[i][j] || (g[i][k] && g[k][j]);
				}
		bool isBounded = true;
		for (int i = 1; i < cnt; i++)
			if (g[i][i]) {
				isBounded = false;
				break;
			}
		if (isBounded)cout << "bounded" << endl;
		else cout << "unbounded" << endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JILIN.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值