ZOJ1298, POJ1135 Domino Effect

题目大意:

        你的任务是编写程序,给定多米诺骨牌游戏,计算最后倒下的是哪一张骨牌、在什么时间倒下。这些多米诺骨牌游戏包含一些“关键牌”,他们之间由一行普通骨牌连接。当一张关键牌倒下时,连接这张关键牌的所有行都开始倒下。当倒下的行到达其他还没倒下的关键骨牌时,则这些关键骨牌也开始倒下,同样也使得连接到它的所有行开始倒下。每一行骨牌可以从两个端点中的任何一张关键牌开始倒下,甚至两个端点的关键牌都可以分别倒下,在这种情形下,该行最后倒下的骨牌为中间的某张骨牌。假定骨牌倒下的速度一致。


#include <cstdio>
#include <cstdlib>

const int  MAXN 500
const int  INF 1000000 //无穷大
int n, m;  //关键牌的数目、关键牌之间连接的数目
int Edge[MAXN][MAXN];  //邻接矩阵
int caseno = 1;  //测试数据序号
int time[MAXN]; //tim[i]为第i 张关键牌倒下的时间(最先推倒第0张骨牌,存储时序号已减1)
int S[MAXN];  //S[i]表示关键牌i 的倒下时间是否已计算

void solve_case( )
{
    int i, j, k;  //循环变量
    for( i=0; i<n; i++ )
    {
        time[i] = Edge[0][i]; S[i]=0;
    }
    time[0] = 0;   S[0] = 1;
    for( i=0; i<n-1; i++ )  //Dijkstra算法:从顶点0确定n-1条最短路径
    {
        int MIN = INF, u = 0;
        for( j=0; j<n; j++ )  //选择当前集合T中具有最短路径的顶点u
        {
            if( !S[j] && time[j]< MIN )
            {
                u=j; MIN = time[j];
            }
        }
        S[u] = 1; //将顶点u加入到集合S,表示它的最短路径已求得
        for( k=0; k<n; k++ )  //修改T集合中顶点的dist和path数组元素值
        {
            if( !S[k] && Edge[u][k]<INF && time[u] + Edge[u][k] < time[k] )
            {
                time[k] = time[u] + Edge[u][k];
            }
        }
    }
    double maxtime1 = -INF;   int pos;   //最后倒下的关键牌时间及位置
    for( i=0; i<n; i++ )
    {
        if( time[i]>maxtime1 )
        {
            maxtime1 = time[i];   pos = i;
        }
    }
    double maxtime2 = -INF, t; //每一行中间普通牌倒下的时间最大值及位置
    int pos1, pos2;
    for( i=0; i<n; i++ )
    {
        for( j=0; j<n; j++ )
        {
            t = (time[i]+time[j] + Edge[i][j])/2.0;
            if( Edge[i][j]<INF &&   t > maxtime2 )
            {
                maxtime2 = t;   pos1 = i;   pos2 = j;
            }
        }
    }
    printf( "System #%d\n", caseno++ );  //输出
    printf( "The last domino falls after " );
    if( maxtime2>maxtime1 )
        printf( "%.1f seconds, between key dominoes %d and %d.\n\n",maxtime2, pos1 + 1, pos2 + 1 );
    else printf( "%.1f seconds, at key domino %d.\n\n", maxtime1, pos + 1 );
}

int read_case( ) //读入数据
{
    int i, j;  //循环变量
    int v1, v2, t;  //每对连接的两张关键牌序号、时间
    scanf( "%d %d", &n, &m );
    if( n == 0 && m == 0 )   return 0;
    for( i=0; i<n; i++ )
    {
        for( j=0; j<n; j++ )   Edge[i][j] = INF;  //INF表示没有连接
    }
    for( i=0; i<m; i++ )
    {
        scanf( "%d %d %d", &v1, &v2, &t);
        v1--; v2--;
        Edge[v1][v2] = Edge[v2][v1] = t;
    }
    return 1;
}

int main( )
{
    while( read_case( ) )
        solve_case( );
    return 0;
}


你可能感兴趣的:(最短路径)