POJ 1135 Domino Effect

这是一道多米诺骨牌的题目 从第一块骨牌出发 问最后一块倒下的骨牌在哪 若是端点 直接输出时间和端点 否则输出时间和 最后的骨牌在哪两块之间

怎么说呢 直接用spfa 算出 从1节点到其他节点的单源最短路径 找出最大的
因为作为最短路的最大值 它必定是一条路径 就算有其他的路径到达这个节点 那也是肯定逼这条最短路径要慢的
所以我们从这个最大节点出发 除了最短路径的其他路径都会是没有走过的路径(也就是还能继续走下去
详见注释

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cstdlib>

using namespace std;
const int maxn=505;
const int inf=0x3f3f3f3f;
int n,m,idx;
int head[maxn],d[maxn];
bool vis[maxn];
struct edge
{
    int v,val;
    int nxt;
}edges[maxn*maxn];

void init()//初始化
{
    memset(head,-1,sizeof head);
    memset(vis,false,sizeof vis);
    memset(d,0x3f,sizeof d);
    idx=0;
}

void add(int u,int v,int val)//邻接表存储
{
    edges[idx].v=v;
    edges[idx].val=val;
    edges[idx].nxt=head[u];
    head[u]=idx++;

    edges[idx].v=u;
    edges[idx].val=val;
    edges[idx].nxt=head[v];
    head[v]=idx++;
}

void spfa()//spfa算法   都是套路
{
    queue<int> que;
    que.push(1);
    vis[1]=true;
    d[1]=0;
    while(!que.empty())
    {
        int tmp=que.front();
        que.pop();
        vis[tmp]=false;
        for(int u=head[tmp];u!=-1;u=edges[u].nxt)
        {
            int v=edges[u].v;
            if(d[tmp]+edges[u].val<d[v])
            {
                d[v]=d[tmp]+edges[u].val;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                }
            }
        }
    }
}

int main()
{
    int u,v,cost,test=0;
    while(scanf("%d %d",&n,&m),n||m)
    {
        init();
        while(m--)
        {
            scanf("%d %d %d",&u,&v,&cost);
            add(u,v,cost);
        }
        spfa();
        double tim=0.0;//初始化为0.0  避免考虑只有一个多米诺骨牌的情况
        int domino=1;
        for(int i=2;i<=n;i++)
        {
            if(tim<d[i])//找到最大的最短路径   并记录
            {
                tim=(double)d[i];
                domino=i;
            }
        }
        int le=domino;
        double tt=tim;
        bool flag=true;
        for(u=head[domino];u!=-1;u=edges[u].nxt)//从该节点出发
        {
            if(d[u]+edges[u].val!=d[domino])//如果不是最短路径
            {
                v=edges[u].v;
                double tmp=(double)(edges[u].val-(d[domino]-d[v]))/2.0;//计算这条路径上还能走多久
                if(tt<tmp+tim)
                {
                    tt=tim+tmp;
                    le=v;
                    flag=false;
                }
            }
        }
        if(le>domino) swap(le,domino);
        printf("System #%d\n",++test);
        if(flag) printf("The last domino falls after %.1lf seconds, at key domino %d.\n\n",tim,domino);
        else printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d.\n\n",tt,le,domino);
    }
    return 0;
}