原题链接: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;
}