POJ 1135 Domino Effect(Dijkstra)
http://poj.org/problem?id=1135
题意:
有一些多米若骨牌,其中有一些关键牌.(这些关键牌可以看成无向图的顶点,关键牌之间的普通牌看成是无向图的边). 然后构成了一个具有n个点,m条边的无向图,每条边有行走时间.现在问你最后倒下的骨牌是不是关键牌,且时间是多少?
分析:
最后倒下的骨牌只有两种情况:关键牌或者非关键牌.
由于骨牌都是从1号骨牌开始倒下的,所以我们只需要算出从1点到其他所有点的距离即可算出,其他关键骨牌的倒塌时间的最大值MAX_1.(想想是不是)
然后我们要算出m条边中(包括两端点)的最晚倒塌的骨牌的时间是多少? 对于a点与b点构成的边,假设a点在d[a]倒塌,b点在d[b]倒塌,且边(a,b)的权值(时间)为 edges[i].dist,所以该边中骨牌的最晚倒塌时间为: (d[a]+d[b]+edges[i].dist)/2 (仔细想想是不是) 记录最大的这种值MAX_2且记录该值对应的两个端点编号.
如果MAX_1 < MAX_2,说明最后倒塌的是普通骨牌.
如果MAX_1>=MAX_2,说明最后倒塌的是关键骨牌.
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn= 500+10;
int n,m;
struct Edge
{
int from,to;
double dist;
Edge(){}
Edge(int from,int to,double d):from(from),to(to),dist(d){}
}e[maxn*maxn];
struct HeapNode
{
double dist;
int u;
HeapNode(double dist,int u):dist(dist),u(u){}
bool operator < (const HeapNode &rhs) const
{
return dist > rhs.dist;
}
};
struct Dijkstra
{
int n,m;
vector<Edge> edges;
vector<int> G[maxn];
bool done[maxn];
double d[maxn];
void init(int n)
{
this->n=n;
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,double dist)
{
edges.push_back(Edge(from,to,dist) );
m=edges.size();
G[from].push_back(m-1);
}
void dijkstra()
{
priority_queue<HeapNode> Q;
for(int i=0;i<n;i++) d[i]= 1e15;
d[0]=0.0;
Q.push(HeapNode(d[0],0));
memset(done,0,sizeof(done));
while(!Q.empty())
{
HeapNode x=Q.top(); Q.pop();
int u =x.u;
if(done[u]) continue;
done[u]=true;
for(int i=0;i<G[u].size();i++)
{
Edge &e=edges[G[u][i]];
if(d[e.to] > d[u]+e.dist)
{
d[e.to] = d[u]+e.dist;
Q.push(HeapNode(d[e.to],e.to));
}
}
}
}
}DJ;
int main()
{
int kase=1;
while(scanf("%d%d",&n,&m)==2&&n)
{
DJ.init(n);
for(int i=0;i<m;i++)
{
scanf("%d%d%lf",&e[i].from,&e[i].to,&e[i].dist);
e[i].from--;
e[i].to--;
DJ.AddEdge(e[i].from,e[i].to,e[i].dist);
DJ.AddEdge(e[i].to,e[i].from,e[i].dist);
}
DJ.dijkstra();
double max_v1=-1;
int max_v1_point;
for(int i=0;i<n;i++)if(max_v1 < DJ.d[i])
{
max_v1 = DJ.d[i];
max_v1_point = i;
}
double max_v2=-1;
int max_v2_p1,max_v2_p2;
for(int i=0;i<m;i++)
{
int u=e[i].from, v=e[i].to, dist=e[i].dist;
if(max_v2 < (DJ.d[u]+DJ.d[v]+dist)/2)
{
max_v2 = (DJ.d[u]+DJ.d[v]+dist)/2;
max_v2_p1 = min(u,v);
max_v2_p2 = max(u,v);
}
}
if(max_v1 < max_v2)
{
printf("System #%d\nThe last domino falls after ",kase++);
printf("%.1lf seconds, between key dominoes %d and %d.\n\n",max_v2,max_v2_p1+1,max_v2_p2+1);
}
else
{
printf("System #%d\nThe last domino falls after ",kase++);
printf("%.1lf seconds, at key domino %d.\n\n",max_v1,max_v1_point+1);
}
}
return 0;
}