P2149 [SDOI2009]Elaxia的路线
Posted jiudushenbeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2149 [SDOI2009]Elaxia的路线相关的知识,希望对你有一定的参考价值。
题目传送门
题目描述
最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。
Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。
现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。
输入输出格式
输入格式:
第一行:两个整数N和M(含义如题目描述)。
第二行:四个整数x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,1 ≤ y2 ≤ N),分别表示Elaxia的宿舍和实验室及w**的宿舍和实验室的标号(两对点分别 x1,y1和x2,y2)。
接下来M行:每行三个整数,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),表 u和v之间有一条路,经过这条路所需要的时间为l。
输出格式:
一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)
输入输出样例
说明
对于30%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N ≤ 1500,输入数据保证没有重边和自环。
这题是我见过最毒瘤的题,没有之一。数组范围真的是太迷了,卡了我一天。
思路:首先当我们拿到题面时,发现出题人还是蛮友善的,直接把要求的问题写了出来。
然后我们就要思考如何记录最短路上的路径,我们可以很容易推出,如果有一条从x到y权值为z的边。从起点1到x的最短路+从y到终点1的最短路+z如果等于从起点1到终点1的最短路并且从起点2到x的最短路+从y到终点2的最短路+z也等于从起点2到终点2的最短路,
就说明这条边是在最短路上的。既然要求最短路的最长公共路径,我们就需要把符合条件的边重新构建出一张有向图,然后跑一边记搜。当然,最短路不止一条。要分别建两次图和记搜两次。(虽然这不符合出题人意图,但也能A)出题人可能没想到这么多
下面为大家提供两份参考代码,一份用的dijkstra堆优化求得最短路,另一份使用SPFA求最短路
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef pair<int,int> P; 4 int n,m,x1,x2,yy1,y2,dis[5][50005],f[40005],next[5000005],first[10005],to[5000005],v[5000005],tot; 5 int ans,book[10005],dp[10005],tot1,next1[5000005],first1[20005],to1[5000005],v1[5000005]; 6 void add(int x,int y,int z) 7 8 tot++; 9 next[tot]=first[x]; 10 first[x]=tot; 11 to[tot]=y; 12 v[tot]=z; 13 14 void add2(int x,int y,int z) 15 16 tot1++; 17 next1[tot1]=first1[x]; 18 first1[x]=tot1; 19 to1[tot1]=y; 20 v1[tot1]=z; 21 book[x]=book[y]=1; 22 23 void dijk(int t,int num) 24 25 priority_queue<P,vector<P>,greater<P> >q; 26 for(int i=1;i<=n;i++) f[i]=false; 27 dis[num][t]=0; 28 q.push(P(0,t)); 29 while(!q.empty()) 30 31 int x=q.top().second; 32 q.pop(); 33 if(f[x]==true) continue; 34 f[x]=true; 35 for(int i=first[x];i;i=next[i]) 36 37 int y=to[i]; 38 if(dis[num][y]>dis[num][x]+v[i]) 39 40 dis[num][y]=dis[num][x]+v[i]; 41 q.push(P(dis[num][y],y)); 42 43 44 45 46 void dp1(int x) 47 48 if(dp[x]!=0) return ; 49 for(int i=first1[x];i;i=next1[i]) 50 51 int y=to1[i]; 52 dp1(y); 53 dp[x]=max(dp[x],dp[y]+v1[i]); 54 55 56 int main() 57 58 memset(dis,999999,sizeof(dis)); 59 scanf("%d %d\n%d %d %d %d",&n,&m,&x1,&yy1,&x2,&y2); 60 for(int i=1;i<=m;i++) 61 62 int xx,yy,zz; 63 scanf("%d %d %d",&xx,&yy,&zz); 64 add(xx,yy,zz); 65 add(yy,xx,zz); 66 67 dijk(x1,1); 68 dijk(x2,2); 69 dijk(yy1,3); 70 dijk(y2,4); 71 for(int i=1;i<=n;i++) 72 73 for(int j=first[i];j;j=next[j]) 74 75 int y=to[j]; 76 if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1]) 77 78 if(dis[4][i]+dis[2][y]+v[j]==dis[2][y2]) add2(y,i,v[j]); 79 80 81 82 for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i); 83 for(int i=1;i<=n;i++) ans=max(ans,dp[i]); 84 memset(dp,0,sizeof(dp)); 85 memset(first1,0,sizeof(first1)); 86 memset(next1,0,sizeof(next1)); 87 memset(to1,0,sizeof(to1)); 88 memset(v1,0,sizeof(v1)); 89 tot1=0; 90 for(int i=1;i<=n;i++) 91 92 for(int j=first[i];j;j=next[j]) 93 94 int y=to[j]; 95 if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1]) 96 97 if(dis[2][i]+dis[4][y]+v[j]==dis[2][y2]) add2(i,y,v[j]); 98 99 100 101 for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i); 102 for(int i=1;i<=n;i++) ans=max(ans,dp[i]); 103 printf("%d",ans); 104 return 0; 105
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef pair<int,int> P; 4 int n,m,x1,x2,yy1,y2,dis[5][50005],f[40005],next[5000005],first[10005],to[5000005],v[5000005],tot; 5 int ans,book[10005],dp[10005],tot1,next1[5000005],first1[20005],to1[5000005],v1[5000005]; 6 void add(int x,int y,int z) 7 8 tot++; 9 next[tot]=first[x]; 10 first[x]=tot; 11 to[tot]=y; 12 v[tot]=z; 13 14 void add2(int x,int y,int z) 15 16 tot1++; 17 next1[tot1]=first1[x]; 18 first1[x]=tot1; 19 to1[tot1]=y; 20 v1[tot1]=z; 21 book[x]=book[y]=1; 22 23 void spfa(int t,int num) 24 25 queue<int>q; 26 for(int i=1;i<=n;i++) f[i]=false; 27 dis[num][t]=0; 28 q.push(t); 29 f[t]=true; 30 while(!q.empty()) 31 32 int x=q.front(); 33 q.pop(); 34 f[x]=false; 35 for(int i=first[x];i;i=next[i]) 36 37 int y=to[i]; 38 if(dis[num][y]>dis[num][x]+v[i]) 39 40 dis[num][y]=dis[num][x]+v[i]; 41 if(f[y]==false) 42 43 q.push(y); 44 f[y]=true; 45 46 47 48 49 50 51 void dp1(int x) 52 53 if(dp[x]!=0) return ; 54 for(int i=first1[x];i;i=next1[i]) 55 56 int y=to1[i]; 57 dp1(y); 58 dp[x]=max(dp[x],dp[y]+v1[i]); 59 60 61 int main() 62 63 memset(dis,999999,sizeof(dis)); 64 scanf("%d %d\n%d %d %d %d",&n,&m,&x1,&yy1,&x2,&y2); 65 for(int i=1;i<=m;i++) 66 67 int xx,yy,zz; 68 scanf("%d %d %d",&xx,&yy,&zz); 69 add(xx,yy,zz); 70 add(yy,xx,zz); 71 72 spfa(x1,1); 73 spfa(x2,2); 74 spfa(yy1,3); 75 spfa(y2,4); 76 for(int i=1;i<=n;i++) 77 78 for(int j=first[i];j;j=next[j]) 79 80 int y=to[j]; 81 if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1]) 82 83 if(dis[4][i]+dis[2][y]+v[j]==dis[2][y2]) add2(y,i,v[j]); 84 85 86 87 for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i); 88 for(int i=1;i<=n;i++) ans=max(ans,dp[i]); 89 memset(dp,0,sizeof(dp)); 90 memset(first1,0,sizeof(first1)); 91 memset(next1,0,sizeof(next1)); 92 memset(to1,0,sizeof(to1)); 93 memset(v1,0,sizeof(v1)); 94 tot1=0; 95 for(int i=1;i<=n;i++) 96 97 for(int j=first[i];j;j=next[j]) 98 99 int y=to[j]; 100 if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1]) 101 102 if(dis[2][i]+dis[4][y]+v[j]==dis[2][y2]) add2(i,y,v[j]); 103 104 105 106 for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i); 107 for(int i=1;i<=n;i++) ans=max(ans,dp[i]); 108 printf("%d",ans); 109 return 0; 110
以上是关于P2149 [SDOI2009]Elaxia的路线的主要内容,如果未能解决你的问题,请参考以下文章
洛谷—— P2149 [SDOI2009]Elaxia的路线