http://poj.org/problem?id=1135
经过无数的WA和PE终于AC。。
最短路的模板。
1)dis[i]表示i到源点1的最短路径,代表每一张关键牌倒下的时间,并求出最大的最短路径ans1。
2)枚举任意两边,计算每一行倒下的时间,设每一行两端的关键牌是i,j。那么这一行完全倒下时间是(dis[i]+dis[j]+map[i][j])/2.0,并求出最大值ans2.
3)比较ans1与ans2,取较大者。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define LL long long
#define _LL __int64
using namespace std;
const int maxn = 510;
const int INF = 0x3f3f3f3f;
int n,m;
int map[maxn][maxn];
int dis[maxn],vis[maxn],maxdis,maxpos;
void dijstra()
{
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
maxdis = -INF;
vis[1] = 1;
for(int i = 1; i <= n; i++)
dis[i] = map[1][i];
for(int i = 1; i < n; i++)
{
int min = INF,pos = 1;
for(int j = 1; j <= n; j++)
{
if(!vis[j] && dis[j] < min)
{
min = dis[j];
pos = j;
}
}
if(min == INF) break;
vis[pos] = 1;
if(maxdis < min)
{
maxdis = min;
maxpos = pos;
}
for(int j = 1; j <= n; j++)
{
if(!vis[j] && dis[j] > dis[pos] + map[pos][j])
dis[j] = dis[pos] + map[pos][j];
}
}
}
void solve()
{
int pl = -1,pr = -1;
double ans2 = (double)maxdis;
double ans1 = -INF;
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++)
{
if(map[i][j] != INF)
{
double res = ( dis[i]+dis[j] + map[i][j])/2.0;
if(res > ans1)
{
ans1 = res;
pl = i;
pr = j;
}
}
}
}
if(ans1 > ans2)
printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n",ans1,pl,pr);
else printf("The last domino falls after %.1f seconds, at key domino %d.\n",ans2,maxpos);
}
int main()
{
int item = 1;
while(~scanf("%d %d",&n,&m) && (n || m))
{
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(i == j) map[i][j] = 0;
else map[i][j] = INF;
}
}
int u,v,w;
for(int i = 1; i <= m; i++)
{
scanf("%d %d %d",&u,&v,&w);
map[u][v] = map[v][u] = w;
}
printf("System #%d\n",item++);
if(n == 1)
{
printf("The last domino falls after 0.0 seconds, at key domino 1.\n\n");
continue;
}
dijstra();
solve();
printf("\n");
}
return 0;
}