题目链接
Floyd+位运算
两点之间的公司用二进制表示,只取重叠的公司,用Floyd松弛边。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int Maxn = 200+10;
const int INF = 0x3f3f3f3f;
int G[Maxn][Maxn];
char str[30];
void floyd(int n) {
for(int k = 1; k <= n; ++k) {
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j) {
if(k == i || k == j) continue;
if(i == j || !G[i][k] || !G[k][j]) continue;
G[i][j] |= (G[i][k]&G[k][j]);
}
}
}
}
int main(void)
{
int n;
while(scanf("%d", &n) != EOF) {
if(!n) break;
memset(G, 0, sizeof(G));
int u, v;
while(scanf("%d%d", &u, &v)) {
if(u == 0 && v == 0) break;
scanf("%s", str);
int tmp = 0;
for(int i = 0; i < strlen(str); ++i)
tmp |= 1<<(str[i]-'a');
G[u][v] = tmp;
}
floyd(n);
while(scanf("%d%d", &u, &v)) {
if(u == 0 && v == 0) break;
int tmp = G[u][v];
if(tmp == 0) {
printf("-\n");
} else {
for(int i = 0; i < 26; ++i) {
if(((tmp>>i)&1) == 0) continue;
printf("%c", i+'a');
}
puts("");
}
}
puts("");
}
return 0;
}