Fiber Network ZOJ 1967(Floyd+二进制状态压缩)

Description

Several startup companies have decided to build a better Internet, called the "FiberNet". They have already installed many nodes that act as routers all around the world. Unfortunately, they started to quarrel about the connecting lines, and ended up with every company laying its own set of cables between some of the nodes. 
Now, service providers, who want to send data from node A to node B are curious, which company is able to provide the necessary connections. Help the providers by answering their queries.

Input

The input contains several test cases. Each test case starts with the number of nodes of the network n. Input is terminated by n=0. Otherwise, 1<=n<=200. Nodes have the numbers 1, ..., n. Then follows a list of connections. Every connection starts with two numbers A, B. The list of connections is terminated by A=B=0. Otherwise, 1<=A,B<=n, and they denote the start and the endpoint of the unidirectional connection, respectively. For every connection, the two nodes are followed by the companies that have a connection from node A to node B. A company is identified by a lower-case letter. The set of companies having a connection is just a word composed of lower-case letters. 
After the list of connections, each test case is completed by a list of queries. Each query consists of two numbers A, B. The list (and with it the test case) is terminated by A=B=0. Otherwise, 1<=A,B<=n, and they denote the start and the endpoint of the query. You may assume that no connection and no query contains identical start and end nodes.

Output

For each query in every test case generate a line containing the identifiers of all the companies, that can route data packages on their own connections from the start node to the end node of the query. If there are no companies, output "-" instead. Output a blank line after each test case.

Sample Input

3
1 2 abc
2 3 ad
1 3 b
3 1 de
0 0
1 3
2 1
3 2
0 0
2
1 2 z
0 0
1 2
2 1
0 0
0

Sample Output

ab
d
-

z
-

 

题目意思:n个路由器,编号1-n,26个公司,编号a-z,路由器之间有一些有向边,边权为一个字符串,字符串由小写字母组成,表示字符串对应的公司能使这条边连通。现在给若干个查询,查询能使任意2个路由器连通的公司。输出公司号,若不存在公司则输出‘-’。

解题思路:本题并不是求最短路,但是却要用到Floyd算法求解最短路的思想。题目就是要求能使任意2个路由器连通的公司的集合,所以可以使用Floyd传递闭包建立联系。另外,在本题中需要很巧妙地处理公司集合,公司是一个小写字母标识,最多只有26个公司,这样可以使用整数二进制位代表每个公司实现集合的状态压缩。

例如,站点1到站点2连接的公司有集合{ ‘a’ , 'b' ,  'c' },可以用“00000000000000000000000111”表示,

            站点2到站点3连接的公司有集合{ ‘a’ , 'd' } ,可以用“00000000000000000000001001”表示,

            这两个整数进行二进制与运算后得到“00000000000000000000000001”表示通过中间站点2,站点1到站点3的连接的公司是集合{ ‘ a ’ }。

 

floyd的本质是枚举中间节点k,使节点i到j的距离最大或最小。针对本题,是要求一个集合,使从i到j连通的公司,那么枚举k的时候,就要求保证i->k和k->j同时连通的公司,状态压缩的话,直接将dis[i][k]和dis[k][j]相与便是结果,这个结果要加到dis[i][j]上去,所以再和dis[i][j]相或。所以总的方程就是:

dis[i][j] = dis[i][j] | (dis[i][k]&dis[k][j])。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int dis[210][210];
 6 int n,m;
 7 void Floyd()
 8 {
 9     int i,j,k;
10     for(k=1; k<=n; k++)
11     {
12         for(i=1; i<=n; i++)
13         {
14             for(j=1; j<=n; j++)
15             {
16                 dis[i][j]|=(dis[i][k]&dis[k][j]);
17             }
18         }
19     }
20 }
21 int main()
22 {
23     int a,b,i;
24     int len;
25     char s[30];
26     while(scanf("%d",&n)!=EOF)
27     {
28         if(n==0)
29         {
30             break;
31         }
32         memset(dis,0,sizeof(dis));
33         while(scanf("%d%d",&a,&b)!=EOF)
34         {
35             if(a==0&&b==0)
36             {
37                 break;
38             }
39             scanf("%s",s);
40             len=strlen(s);
41             for(i=0; i<len; i++)
42             {
43                 dis[a][b]|=(1<<(s[i]-'a'));///逻辑左移s[i]-'a'位
44             }
45         }
46         Floyd();
47         while(scanf("%d%d",&a,&b)!=EOF)
48         {
49             if(a==0&&b==0)
50             {
51                 break;
52             }
53             if(dis[a][b])
54             {
55                 for(i=0; i<26; i++)
56                 {
57                     if(dis[a][b]&(1<<i))///如果dis[a][b]&(1<<i)!=0,说明dis[a][b]所代表的集合中包含公司'a'+i
58                     {
59                         putchar('a'+i);
60                     }
61                 }
62             }
63             else
64             {
65                 putchar('-');
66             }
67             putchar('
');
68         }
69         putchar('
');
70     }
71     return 0;
72 }
原文地址:https://www.cnblogs.com/wkfvawl/p/9552764.html