hdu2066 一个人的旅行 最短路

单源最短路裸题

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define min(a,b) (a)<(b)?a:b
 4 #define INF 100001
 5 int T,S,D,dist[1050],v[1050][1050],m,l[1050],r[1050];
 6 
 7 void DIJKSTRA(int x){
 8     int i,j,mi,minj;
 9     bool visit[1050]={0};
10     for(i=1;i<=m;i++)dist[i]=v[x][i];
11     visit[x]=1;
12     for(i=1;i<m;i++){
13         mi=INF;
14         for(j=1;j<=m;j++){
15             if(!visit[j]&&dist[j]<mi){
16                 mi=dist[j];
17                 minj=j;
18             }
19         }
20         if(mi==INF) return;
21         visit[minj]=1;
22         for(j=0;j<=m;j++){
23             if(!visit[j]&&dist[j]>dist[minj]+v[minj][j]){
24                 dist[j]=dist[minj]+v[minj][j];
25             }
26         }
27     }
28 }
29 
30 
31 int main(){
32     while(scanf("%d%d%d",&T,&S,&D)!=EOF){
33         int q,tm=0xFFFFFFF,i,j;
34         for(i=1;i<1050;i++){
35             for(j=1;j<1050;j++){
36                 v[i][j]=INF;
37             }
38         }
39         m=-1;
40         for(q=1;q<=T;q++){
41             int a,b,va;
42             scanf("%d%d%d",&a,&b,&va);
43             v[a][b]=v[b][a]=min(va,v[a][b]);
44             if(a>m)m=a;
45             if(b>m)m=b;
46         }
47         for(q=1;q<=S;q++)scanf("%d",&l[q]);
48         for(q=1;q<=D;q++)scanf("%d",&r[q]);
49         for(i=1;i<=S;i++){
50             DIJKSTRA(l[i]);
51             for(j=1;j<=D;j++){
52                 if(dist[r[j]]<tm)tm=dist[r[j]];
53             }
54         }
55         printf("%d
",tm);
56     }
57     return 0;
58 }
View Code

以前不太懂,头硬直接跑了s遍没有优化的dijkstra,每遍循环看下d个点取最优也能过,复杂度应该是O( s * (n^2) ),那么大概s不是很大,所以据说O(n^3)的floyd过不了(据说,我也不清楚),但是这样都能过。

不过现在重新看,这个题对于初学者来说应该还是很有亮点的。

它的s个起点、d个终点可以为其建立一个源点一个汇点,这样源点有条边到每个可行起点,而每个可行终点有条边到汇点,只需要从源点到汇点跑一次单源最短路,无需遍历终点直接输出汇点的dis就是答案了。

这种题当时要是没有水过去,而是被卡了找找网上的分析,应该很有帮助吧。

 1 #include<stdio.h>        //基本需要的头文件
 2 #include<string.h>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 const int INF=0x3f3f3f3f;
 7 
 8 const int maxn=1e3+5;
 9 const int maxm=1e5+5;
10 
11 struct pii{
12     int dis;
13     int s;
14     bool operator < (const pii x)const{
15         return dis > x.dis;
16     }
17     pii(int a,int b):dis(a),s(b){};
18 };
19 int head[maxn],nxt[maxm<<1],val[maxm<<1],point[maxm<<1],size;
20 int dis[maxn];
21 
22 void init(){
23     memset(head,-1,sizeof(head));
24     size=0;
25 }
26 
27 void add(int a,int b,int v){
28     point[size]=b;
29     val[size]=v;
30     nxt[size]=head[a];
31     head[a]=size++;
32 }
33 
34 void dij(int s,int t){            //传入出发点和到达点
35     int i;
36     priority_queue<pii>q;
37     q.push(pii(0,s));
38     memset(dis,0x3f,sizeof(dis));
39     dis[s]=0;
40     while(!q.empty()){
41         pii u=q.top();
42         q.pop();
43         if(u.dis>dis[u.s])continue;
44         for(i=head[u.s];~i;i=nxt[i]){
45             int j=point[i];
46             if(dis[j]>u.dis+val[i]){
47                 dis[j]=u.dis+val[i];
48                 q.push(pii(dis[j],j));
49             }
50         }
51     }
52     printf("%d
",dis[t]);        //或去掉在主函数中输出或操作
53 }
54 
55 int main(){
56     int t,s,d;
57     while(scanf("%d%d%d",&t,&s,&d)!=EOF){
58         init();
59         while(t--){
60             int a,b,v;
61             scanf("%d%d%d",&a,&b,&v);
62             add(a,b,v);
63             add(b,a,v);
64         }
65         for(int i = 1 ; i <= s ; ++ i){
66             int a;
67             scanf("%d",&a);
68             add(0,a,0);
69         }
70         for(int i = 1 ; i <= d ; ++ i){
71             int a;
72             scanf("%d",&a);
73             add(a,1001,0);
74         }
75         dij(0,1001);
76     }
77     return 0;
78 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/6577973.html