poj 2570 Fiber Network floyd + 位运算
题意:一些公司共同拥有一个具有n个顶点的网络,给出了有关于这个网络的信息,即边<i,j>以及与这条边相连的公司,现在题目给出一条路径的起点和终点,要求求出这条路径经过哪些公司.
很容易想到求图的传递闭包,而这里两点之间可能有多条线路,之前对每个字母(也就是每个公司)单独来进行一遍Floyd,结果超时了,这里输入的公司标志为不同的小写字母,最多只有26个,所以我们可以根据位运算来进行优化。
floyd + 位运算
考虑到相邻两条边都被一个公司拥有当且仅当两条边上都有该公司对应的字母,位运算&能有获得两个公司的公共位,新边并上(|)这个结果就表示新边所属的公司
View Code
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define re(i,n) for(int i=1;i<=n;i++) const int maxn = 202; int map[maxn][maxn]; int n; void floyd() { re(k,n) re(i,n) { if(i==k | !map[i][k]) continue; re(j,n) { if(j==k || !map[k][j]) continue; map[i][j] |= map[i][k] & map[k][j]; } } } int main() { while(~scanf("%d",&n) && n) { int u,v; char c; memset(map,0,sizeof(map)); while(scanf("%d%d",&u,&v)) { if(u==0 && v==0) break; for(;(c=getchar())!='\n';map[u][v]|=1<<c-'a'); } floyd(); while(scanf("%d%d",&u,&v)) { if(u==0 && v==0) { putchar('\n');break; } bool ok = 0; for(int i=0;i<26;i++) { if(map[u][v] & 1<<i) ok = 1 , putchar('a'+i); } if(!ok) putchar('-'); putchar('\n'); } } return 0; }