hnu rounting 解题报告

题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=11532&courseid=135

题目大意:在一个无向图中求一个点到另外两个点的距离之和的最小值,如果有一段距离是他们公用的只能算一次,比如c到a,b.如果最短距离是有c到d之后到a,b的,只能算cd+da+db。
设源点为S,另外两个点为A、B。
我们可以先这样想:假如S到A、B两个点的最短路径没有交叉,那么结果就是dist[A]+dist[B];其实这个值也是最大值。如果有交叉的情况又是什么样的呢?假设交叉点是C,C到A、B的最短距离是dist1[A]、dist1[B]。那么结果很显然就是 dist[C]+dist1[A]+dist1[B];我们枚举所有的C点,求取最小的dist[C]+dist1[A]+dist1[B],不就OK了吗。
然而再想想时间复杂度吧,以上做法可能会达到O(n^3)的复杂度,5000个点会超时的。
其实我们仔细想一想就知道,我们没必要枚举所有的C点,我们只要求出S、A、B到其余个点的最短距离就可以了,正好和刚在所说的是相反的过程,刚才我们求的是其余所有点到S、A、B的最短距离,而现在呢,则是三个点到其余各点的最短距离(想一想为什么),这样我们只求三次最短路径,降低了时间复杂度。
也就是3次Dij+O(n)的遍历。

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 using namespace std;
5 const int INF= 100000000;
6 struct ss{
7 int y,z,next;
8 }edge[20005];
9 int head[5005];
10 int dist1[5005],dist2[5005],dist3[5005],dist[5005];
11 int vist[5005];
12 int n,N;
13 void Dij(int s)
14 {
15 int i,j,v,ma;
16 for(i=1;i<=n;i++)
17 {
18 dist[i]=INF;
19 vist[i]=0;
20 }
21 for(i=head[s];i;i=edge[i].next)
22 {
23 dist[edge[i].y]=edge[i].z;
24 }
25 vist[s]=1;
26 dist[s]=0;
27 for(i=1;i<n;i++)
28 {
29 ma=INF;
30 for(j=1;j<=n;j++)
31 if(!vist[j]&&dist[j]<ma)
32 {
33 v=j;
34 ma=dist[j];
35 }
36 if(ma==INF)return ;
37 vist[v]=1;
38 for(j=head[v];j;j=edge[j].next)
39 {
40 if(!vist[edge[j].y]&&dist[edge[j].y]>dist[v]+edge[j].z)
41 dist[edge[j].y]=dist[v]+edge[j].z;
42 }
43 }
44 }
45 int main()
46 {
47 int m,i,a,b,c,x,y,z,sum,kk=0;
48 while(scanf("%d%d",&n,&m)!=EOF)
49 {
50 kk++;
51 N=1;
52 memset(head,0,sizeof(head));
53 scanf("%d%d%d",&a,&b,&c);
54 for(i=1;i<=m;i++)
55 {
56 scanf("%d%d%d",&x,&y,&z);
57 edge[N].y=y;
58 edge[N].z=z;
59 edge[N].next=head[x];
60 head[x]=N++;
61 edge[N].y=x;
62 edge[N].z=z;
63 edge[N].next=head[y];
64 head[y]=N++;
65 }
66 Dij(a);
67 for(i=1;i<=n;i++)
68 dist1[i]=dist[i];
69 if(dist1[b]==INF||dist1[c]==INF)
70 {
71 printf("Scenario #%d\n",kk);
72 printf("Can not reach!\n\n");
73 continue;
74 }
75
76 Dij(b);
77 for(i=1;i<=n;i++)
78 dist2[i]=dist[i];
79 Dij(c);
80 for(i=1;i<=n;i++)
81 dist3[i]=dist[i];
82
83 sum=INF;
84 for(i=1;i<=n;i++)
85 {
86 m=dist1[i]+dist2[i]+dist3[i];
87 if(m<sum)
88 sum=m;
89 }
90 printf("Scenario #%d\n",kk);
91 printf("%d\n\n",sum);
92 }
93 return 0;
94 }
posted @ 2012-03-13 14:26  我们一直在努力  阅读(166)  评论(0编辑  收藏  举报