POJ Fiber Network 2570

来源:互联网 发布:mac win7截图 编辑:程序博客网 时间:2024/06/15 05:04

/**

本题不是求最短路径,但是用的是Floyd算法思想;
我们先设m[MAXN][MAXN],m[i][j]表示从i到j的公司数目;
m(0)[i][j]表示提供从i到j能直接达到的集合,
m(1)[i][j]表示以(如果存在,则)v1为中间点,能提供从i到j的集合
······························
······························
m(k)[i][j]表示以顶点序号不超过k,能提供从i到j的集合

先交代一下:本题中字母全是小写,因而最多共有26个小写字母,可以用二进制形式来表述,
例如:
    a  000000000001
    b  000000000010
    c  000000000100
    ab 000000000011
    abc 00000000111
每一个单个字母ch1可以看成是:1<< (ch1 - 'a')
多个字母可以看成ch1|ch2;

综上:Floyd算法可以修改为:
------------------------------
m(0)[A][B] 为从A能直接到B的集合
m(k)[A][B] = {m(k-1)[A][B] | m(k-1)[A][k] & m(k-1)[k][B]}
(同理于:m[i][j] |= m[i][k] & m[k][j])
------------------------------
*/

 

#include <iostream>#include <cstring>using namespace std;const int MAXN = 210;int m[MAXN][MAXN];int n;int main(){    char ch;    char str[MAXN];    int A, B;    while( 1 )    {        int i, j, k;        cin>>n;        if( n == 0 )            break;        memset( m, 0, sizeof( m ));        while( cin >> A >> B )        {            if( A == 0 && B == 0 )                break;            cin>>str;            for( i = 0; str[i]; ++i )                m[A][B] |= 1 << (str[i] - 'a');        }        for(k = 1; k <= n; ++k)//floyd算法        {            for(i = 0; i <= n; ++i)            {                for(j = 1; j <= n; ++j)                {                    m[i][j] |= m[i][k] & m[k][j];//如果没有这样的vk点,则m[i][j]保持的仍是k-1时的m[i][j]                }            }        }        while( cin >> A >> B )        {            if( A == 0 && B == 0)                break;            for( ch = 'a'; ch <= 'z'; ++ch)                if(m[A][B] & (1 << (ch - 'a') ))//为真,则有该字母                    cout<<ch;            if( !m[A][B])                cout<<"-";            cout<<endl;        }        cout<<endl;    }    return 0;}