Problem: http://poj.org/problem?id=1135
求图中距离1点最远(包括点和边上的点)的距离
先对所有点求单源(点1)最短路
然后每条边上的点距离1点最远的距离必为边两端点到点1的最短距离和该边的长度 三者和的一半
现在点到源(点1)的距离知道了 边到源(点1)的距离也知道了 只需要比较两者了
#include<cstdio> #include<queue> #include<cstring> using namespace std; #define MAXN 510 #define MAXE 250010 int n,m,size,head[MAXN],A[MAXE],B[MAXE],pre[MAXN]; double C[MAXE],dist[MAXN]; bool vis[MAXN]; struct Edge{ int to,next; double w; }e[MAXE<<1]; void add_edge(int u,int v,double w){//链式前向星存图 e[size].to=v; e[size].w=w; e[size].next=head[u]; head[u]=size++; } void Seap(int &a,int &b){ int c=a; a=b; b=c; } void work(int s){ for(int i=1;i<=n;i++)dist[i]=-1; memset(vis,false,sizeof(vis)); dist[s]=0; priority_queue<pair<double,int> > heap;//优先队列实现堆 heap.push(make_pair(0,s)); while(!heap.empty()){//堆优化Dijkstra int u=heap.top().second; heap.pop(); if(vis[u])continue; vis[u]=true; int k=head[u]; while(k>=0){ if(dist[e[k].to]<0 || dist[e[k].to]>dist[u]+e[k].w){ pre[e[k].to]=u; dist[e[k].to]=dist[u]+e[k].w; heap.push(make_pair(-dist[e[k].to],e[k].to)); } k=e[k].next; } } int k1,k2; double ans1=0,ans2=0; for(int i=1;i<=n;i++){//求距源最远的点 if(dist[i]>ans1){ ans1=dist[i]; k1=i; } } for(int i=0;i<m;i++){//求距源最远的边 double l=dist[A[i]]+dist[B[i]]+C[i]; if(l/2>ans2){ ans2=l/2; k2=i; } } printf("The last domino falls after "); if(ans1>=ans2)printf("%.1f seconds, at key domino %d.\n",ans1,k1); else{ if(A[k2]>B[k2])Seap(A[k2],B[k2]); printf("%.1f seconds, between key dominoes %d and %d.\n",ans2,A[k2],B[k2]); } } void init(){ size=0; memset(head,-1,sizeof(head)); for(int i=0;i<m;i++){ scanf("%d%d%lf",&A[i],&B[i],&C[i]); add_edge(A[i],B[i],C[i]); add_edge(B[i],A[i],C[i]); } } int main(){ int t=0; while(scanf("%d%d",&n,&m),n+m){ init(); printf("System #%d\n",++t); work(1); printf("\n"); } return 0; }
题中边长l没给范围是个坑,直接用double是明智滴真知>>>>>.<<<<<<