Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1418 Accepted Submission(s): 467
//这题气炸了,用dijk怎么做怎么不对,改了spfa才过的。要求最小差值的最短路可以把所有的点之间的差值 //算出来,按照差值从小到大排序,从小到大枚举每一个差值所对应的高度上下界,在这个范围之内求 //最短路,求到的第一个就是结果。 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> using namespace std; const int inf=0x7fffffff; int dis[105],vis[105],hig[105]; int up,low,t,n,m,cnt; struct Lu { int x,y,w; }L[100005]; bool cmp(Lu x,Lu y) {return x.w<y.w;} struct node{ int to,value; }; vector<node>g[104]; int spfa() { int s=1; for(int i=0;i<=n;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); vis[s]=1; dis[s]=0; queue<int>q; q.push(s); while(!q.empty()){ int cur=q.front(); q.pop(); vis[cur]=0; if(hig[cur]<low||hig[cur]>up) continue; //起始点也不例外 for(int i=0;i<(int)g[cur].size();i++){ int k=g[cur][i].to; if(hig[k]<low||hig[k]>up) continue; //在范围之中 if(dis[k]>dis[cur]+g[cur][i].value){ dis[k]=dis[cur]+g[cur][i].value; if(!vis[k]){ vis[k]=1; q.push(k); } } } } return dis[n]; } int main() { int x,y,z,ans1,ans2; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); cnt=0;ans2=inf; for(int i=1;i<=n;i++){ g[i].clear(); //记住。 scanf("%d",&hig[i]); } for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ //有可能起点等于终点所以j从i开始 L[cnt].x=min(hig[i],hig[j]); L[cnt].y=max(hig[i],hig[j]); L[cnt].w=L[cnt].y-L[cnt].x; cnt++; } } for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); node no; no.to=y; no.value=z; g[x].push_back(no); no.to=x; g[y].push_back(no); } sort(L,L+cnt,cmp); int flag=0,tmp; for(int i=0;i<cnt;i++){ if(flag&&tmp<L[i].w) break;//出现高度差一样,最短路不同的情况 low=L[i].x;up=L[i].y; int ans=spfa(); if(ans!=inf){ ans1=L[i].w; ans2=min(ans2,ans); flag=1; tmp=L[i].w; } } printf("%d %d\n",ans1,ans2); } return 0; }
原文:http://www.cnblogs.com/--ZHIYUAN/p/6290411.html