HDU - 2833 - WuKong
先上题目:
WuKong
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1070 Accepted Submission(s): 384
Problem Description
Liyuan wanted to rewrite the famous book “Journey to the West” (“Xi You Ji” in Chinese pinyin). In the original book, the Monkey King Sun Wukong was trapped by the Buddha for 500 years, then he was rescued by Tang Monk, and began his journey to the west. Liyuan thought it is too brutal for the monkey, so he changed the story:
One day, Wukong left his home - Mountain of Flower and Fruit, to the Dragon King’s party, at the same time, Tang Monk left Baima Temple to the Lingyin Temple to deliver a lecture. They are both busy, so they will choose the shortest path. However, there may be several different shortest paths between two places. Now the Buddha wants them to encounter on the road. To increase the possibility of their meeting, the Buddha wants to arrange the two routes to make their common places as many as possible. Of course, the two routines should still be the shortest paths.
Unfortunately, the Buddha is not good at algorithm, so he ask you for help.
One day, Wukong left his home - Mountain of Flower and Fruit, to the Dragon King’s party, at the same time, Tang Monk left Baima Temple to the Lingyin Temple to deliver a lecture. They are both busy, so they will choose the shortest path. However, there may be several different shortest paths between two places. Now the Buddha wants them to encounter on the road. To increase the possibility of their meeting, the Buddha wants to arrange the two routes to make their common places as many as possible. Of course, the two routines should still be the shortest paths.
Unfortunately, the Buddha is not good at algorithm, so he ask you for help.
Input
There are several test cases in the input. The first line of each case contains the number of places N (1 <= N <= 300) and the number of roads M (1 <= M <= N*N), separated by a space. Then M lines follow, each of which contains three integers a b c, indicating there is a road between place a and b, whose length is c. Please note the roads are undirected. The last line contains four integers A B C D, separated by spaces, indicating the start and end points of Wukong, and the start and end points of Tang Monk respectively.
The input are ended with N=M=0, which should not be processed.
The input are ended with N=M=0, which should not be processed.
Output
Output one line for each case, indicating the maximum common points of the two shortest paths.
Sample Input
6 6
1 2 1
2 3 1
3 4 1
4 5 1
1 5 2
4 6 3
1 6 2 4
0 0
Sample Output
3
Hint: One possible arrangement is (1-2-3-4-6) for Wukong and (2-3-4) for Tang Monk. The number of common points are 3.
题意:给你一个无向图,给出孙悟空的出发地点和目的地点,唐僧的出发地点和目的地地点,问你如果他俩都走最短路的情况下(如果某个人有多条最短路的时候,那么这个人会走相遇点最多的那条),最多可以有多少个相遇的地方。
这一题首先需要先求出两者的最短路,因为这里的点不是很多只有300个,所以可以用Flyod先求出多源最短路,同时需要求出某两点之间的最短路最多有多少个点。为什么需要求某两点最多有多少个点?这里经过分析可以得出,如果两条最短路有相交的部分,那么这些相交的部分一定是连续的。为什么呢?这里的分析和dij的分析一样。因为求最短路的时候对于某一个点延伸出去的时候是选最短的那条路,所以如果该点是重合点,那么如果还有重合点,那就意味着有一段最短路同时存在于两条最短路之间,所以如果我们求最短路的时候顺便把两点之间最短路最多经过了多少个点,那么只要我们枚举两条最短路中间的那一段就可以找到目标的最大值。
求某两点的最短路最多有多少段的状态转移方程:
dp[i][j]= max(dp[i][j],dp[i][u]+ dp[u][j]) dis[i][u]+dis[u][j]<dis[i][j]
dp[i][j] other
在下面的程序里面dp[i][j]的意思是以i、j为端点的最短路最多有多少条边,所以结果要加一。
枚举的时候:(dis[s1][i] + dis[i][j] + dis[j][e1] == dis[s1][e1]) && (dis[s2][i] + dis[i][j] + dis[j][e2] == dis[s2][e2])
枚举的含义是dis[i][j]是s1e1的一段,同时也是s2e2的一段。
上代码:
1 #include <cstdio> 2 #include <cstring> 3 #define max(x,y) (x > y ? x : y) 4 #define MAX 302 5 #define INF 1000000000 6 using namespace std; 7 8 int dis[MAX][MAX],dp[MAX][MAX]; 9 int n,m; 10 11 void flyod(){ 12 for(int u=1;u<=n;u++){ 13 for(int i=1;i<=n;i++){ 14 for(int j=1;j<=n;j++){ 15 if(dis[i][j]>dis[i][u]+dis[u][j]){ 16 dis[i][j]=dis[i][u]+dis[u][j]; 17 dp[i][j]=dp[i][u]+dp[u][j]; 18 }else if(dis[i][j]==dis[i][u]+dis[u][j]){ 19 dp[i][j]=max(dp[i][u]+dp[u][j],dp[i][j]); 20 } 21 } 22 } 23 } 24 } 25 26 int main() 27 { 28 int a,b,l; 29 int s1,e1,s2,e2; 30 int ans; 31 //freopen("data.txt","r",stdin); 32 while(scanf("%d %d",&n,&m),(n+m)){ 33 for(int i=1;i<=n;i++){ 34 for(int j=1;j<=n;j++){ 35 dis[i][j]= i==j ? 0 : INF; 36 dp[i][j]=0; 37 } 38 } 39 for(int i=0;i<m;i++){ 40 scanf("%d %d %d",&a,&b,&l); 41 if(dis[a][b]>l){ 42 dis[a][b]=dis[b][a]=l; 43 dp[a][b]=dp[b][a]=1; 44 } 45 } 46 47 scanf("%d %d %d %d",&s1,&e1,&s2,&e2); 48 flyod(); 49 ans=-1; 50 for(int i=1;i<=n;i++){ 51 for(int j=1;j<=n;j++){ 52 if(dp[i][j]>ans && (dis[s1][e1] == dis[s1][i]+dis[i][j]+dis[j][e1]) 53 && (dis[s2][e2] == dis[s2][i]+dis[i][j]+dis[j][e2]) ){ 54 ans=dp[i][j]; 55 } 56 } 57 } 58 printf("%d\n",ans+1); 59 } 60 return 0; 61 }