// floyd + 位运算
/* 题目大意:有若干家公司,他们分别在若干个城市的路由器间铺设了自己的光纤,
现在问,如果要从路由器A到路由器B传送资料,能否只使用一家公司的光纤而达到目的,
如能则分别输出这些公司的代号。
思路:虽然不是最短路,却可以用每对顶点的最短路径 floyd-warshell 算法来求解。
dist[i][j]代表 i 到 j 的一条可能包含前k个点中若干个顶点的所有路径中最短的路径。
而在本题中
graph[i][j]代表i 到 j 的包含前k个点中若干个顶点的所有路径中的可行解的状态(压缩到整形里位表示)
计算方式为:
graph[i][j] = graph[i][j] | (graph[i][p] & graph[p][j])
最后也就根据要求查询位状态即可。
*/
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 201;
int n;
int graph[maxn][maxn];
void init()
{
int i;
int v1,v2,length;
char company[27];
memset(graph,0,sizeof(graph));
while (scanf("%d %d ",&v1,&v2)&&(v1!=0&&v2!=0))
{
scanf("%s",&company);
length = strlen(company);
for (i=0;i<length;++i)
graph[v1][v2] |= (1<<(company[i]-'a')); //用二进制位来表示城市
}
}
void floyd()
{
int pre,past;
int p,i,j;
for (p=1;p<=n;++p)
{ for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
graph[i][j] = graph[i][j] | (graph[i][p]&graph[p][j]);
}
}
void output()
{
bool any;
int i;
int v1, v2, pre = n & 1;
while (scanf("%d %d",&v1,&v2)&&(v1!=0&&v2!=0))
{
any = false;
for (i=0;i<26;++i)
if (graph[v1][v2]&(1<<i))
{
printf("%c",'a'+i);
any = true;
}
if (!any)printf("-");
putchar('\n');
}
putchar('\n');
}
int main()
{
while (scanf("%d",&n)&&n)
{
init();
floyd();
output();
}
return 0;
}
poj 2570经典二进制floyd
最新推荐文章于 2025-08-10 21:28:09 发布