hdu 1874 畅通工程续

畅通工程续

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 21439    Accepted Submission(s): 7472


Problem Description
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
 

 

Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
 

 

Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
 

 

Sample Input
3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2
 

 

Sample Output
2 -1
 

 

Author
linle
 

 

Source
 

 

Recommend
lcy   |   We have carefully selected several similar problems for you:  1142 2722 1598 2923 2962
 
 
/*

    题意:
        中文...
        
    最短路径:
        直接模板题.
         
*/
 
以下V表示点数,E表示边数
 
1、Dij 算法(单源:O(V^2),所有:O(V^3))
 1 //15MS    284K    1041 B    G++    
 2 #include<stdio.h>
 3 #include<string.h>
 4 #define inf 0x7ffffff
 5 int g[205][205];
 6 int d[205];
 7 int vis[205];
 8 int n,m;
 9 int dij(int u)
10 {
11     memset(vis,0,sizeof(vis));
12     for(int i=0;i<n;i++)
13         d[i]=g[u][i];
14     vis[u]=1;
15     for(int i=1;i<n;i++){
16         int temp=inf;
17         int v=u;
18         for(int j=0;j<n;j++)
19             if(!vis[j] && d[j]<temp){
20                 temp=d[j]; v=j;
21             }
22         vis[v]=1;
23         for(int j=0;j<n;j++)
24             if(!vis[j] && temp+g[v][j]<d[j])
25                 d[j]=temp+g[v][j];
26     }            
27 }
28 int main(void)
29 {
30     int a,b,x;
31     while(scanf("%d%d",&n,&m)!=EOF)
32     {
33         for(int i=0;i<=n;i++)
34             for(int j=0;j<=n;j++){
35                 g[i][j]=inf;
36                 if(i==j) g[i][j]=0;
37             }
38         for(int i=0;i<m;i++){
39             scanf("%d%d%d",&a,&b,&x);
40             if(g[a][b]>x) g[a][b]=g[b][a]=x;
41         }
42         scanf("%d%d",&a,&b);
43         dij(a);
44         printf("%d\n",d[b]==inf?-1:d[b]);
45     }
46     return 0;
47 }
View Code

 

2、 Floyd 算法(所有:O(V^3))

 1 //46MS    308K    765 B    C++ 
 2 #include<stdio.h>
 3 #define N 0x7ffffff
 4 #define min(a,b) (a<b?a:b)
 5 int n,m;
 6 int g[205][205];
 7 void floyd()
 8 {
 9     for(int k=0;k<n;k++)
10         for(int i=0;i<n;i++)
11             for(int j=0;j<n;j++)
12                 g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
13 }
14 int main(void)
15 {
16     int a,b,c;
17     while(scanf("%d%d",&n,&m)!=EOF)
18     {
19         for(int i=0;i<n;i++)
20             for(int j=0;j<n;j++)
21                 if(i==j) g[i][j]=0;
22                 else g[i][j]=N;
23         for(int i=0;i<m;i++){
24             scanf("%d%d%d",&a,&b,&c);
25             if(g[a][b]>c)
26                 g[a][b]=g[b][a]=c;
27         }
28         floyd();
29         scanf("%d%d",&a,&b);
30         if(g[a][b]==N) puts("-1");
31         else printf("%d\n",g[a][b]);
32     }
33     return 0;
34 }
View Code

 

3、Bellman-Ford 算法(单源:O(V*E),所有:O(V^2*E))

 1 //15MS    212K    1338 B    G++
 2 #include<stdio.h>
 3 #include<string.h>
 4 #define inf 0x7ffffff
 5 struct node{
 6     int u,v,w; //代表边的始点、终点、权值 
 7 }edge[1005];
 8 int n,m;
 9 int d[205]; //d[i]表示从源点s到i的最短路径长度 
10 void bellman_ford(int s)
11 {
12     bool flag;
13     for(int i=0;i<n;i++)
14         d[i]=inf;
15     d[s]=0;
16     for(int i=1;i<n;i++){
17         flag=false;
18         for(int k=0;k<2*m;k++){
19             if(d[edge[k].u]+edge[k].w<d[edge[k].v]){ // && d[edge[k].u]!=inf 
20                 flag=true;
21                 d[edge[k].v]=d[edge[k].u]+edge[k].w;
22             }
23         }
24         if(!flag) break;  //优化 
25     }
26     /*
27     //判断是否存在负权值回路 
28     for(int k=0;k<2*m;k++){
29         if(d[edge[k].u]!=inf && d[edge[k].u]+edge[k].w<d[edge[k].v])
30             return false;
31     }
32     return true;
33     */
34 }
35 int main(void)
36 {
37     int u,v,w;
38     while(scanf("%d%d",&n,&m)!=EOF)
39     {
40         int edgenum=0;
41         for(int i=0;i<m;i++){
42             scanf("%d%d%d",&u,&v,&w);
43             edge[edgenum].u=u;
44             edge[edgenum].v=v;
45             edge[edgenum++].w=w;
46             edge[edgenum].u=v;
47             edge[edgenum].v=u;
48             edge[edgenum++].w=w;
49         }
50         scanf("%d%d",&u,&v);
51         bellman_ford(u);
52         if(d[v]==inf) puts("-1");
53         else printf("%d\n",d[v]);
54     }
55     return 0;
56 }
View Code

 

4、SPFA 算法 (单源:O(k*E),所有:O(k*E*N),k<=2)

C实现:

 1 //15MS    220K    1666 B    G++
 2 #include<stdio.h>
 3 #include<string.h>
 4 #define inf 0x7ffffff
 5 struct node{
 6     int u,v,w,next; //分别代表始点、终点、边权值、下一个节点 
 7 }edge[2005]; //邻接表 
 8 int vis[205],Q[205];
 9 int Head[205],d[205],edgenum;
10 int n,m;
11 void addedge(int u,int v,int w) //添加双向边 
12 {
13     edge[edgenum].u=u; //始点储存可有可而无 
14     edge[edgenum].v=v;
15     edge[edgenum].w=w;
16     edge[edgenum].next=Head[u];
17     Head[u]=edgenum++;
18                        
19     edge[edgenum].u=v;
20     edge[edgenum].v=u;
21     edge[edgenum].w=w;
22     edge[edgenum].next=Head[v];
23     Head[v]=edgenum++;
24 }
25 void SPFA(int s)
26 {
27     memset(vis,0,sizeof(vis));
28     for(int i=0;i<n;i++)
29         d[i]=inf;
30     int head=0,tail=1;
31     Q[head]=s;
32     d[s]=0;
33     while(head!=tail){
34         int u=Q[head++];
35         vis[u]=0;
36         for(int i=Head[u];i!=-1;i=edge[i].next){ //遍历点u有关的边 
37             int v=edge[i].v;
38             int w=edge[i].w;
39             if(d[v]>d[u]+w){  //relax松弛法 
40                 d[v]=d[u]+w;
41                 if(!vis[v]){  //不在栈中则进栈 
42                     vis[v]=1;
43                     Q[tail++]=v;
44                     tail%=n; //循环队列,节省空间..下同 
45                 }
46             }
47         }
48         head%=n;
49     }
50 }
51 int main(void)
52 {
53     int u,v,x;
54     while(scanf("%d%d",&n,&m)!=EOF)
55     {
56         memset(Head,-1,sizeof(Head)); //初始化头结点 
57         edgenum=0;
58         for(int i=0;i<m;i++){
59             scanf("%d%d%d",&u,&v,&x);
60             addedge(u,v,x); 
61         }
62         scanf("%d%d",&u,&v);
63         SPFA(u);
64         if(d[v]==inf) puts("-1");
65         else printf("%d\n",d[v]);    
66     }
67     return 0;
68 }
View Code

 C++实现:

 1 //0MS    268K    1251 B    C++    
 2 #include<iostream>
 3 #include<queue>
 4 #include<vector>
 5 #define inf 0x7ffffff 
 6 using namespace std;
 7 struct node{
 8     int v;
 9     int w;
10     node(int a,int b){
11         v=a; w=b;
12     }
13 };
14 vector<node>V[205];
15 int vis[205];
16 int d[205];
17 int n,m;
18 void spfa(int s)
19 {
20     memset(vis,0,sizeof(vis));
21     for(int i=0;i<=n;i++)
22         d[i]=inf;
23     d[s]=0;
24     queue<int>Q;
25     Q.push(s);
26     while(!Q.empty()){
27         int u=Q.front();
28         Q.pop();
29         vis[u]=0;
30         int n0=V[u].size();
31         for(int i=0;i<n0;i++){
32             int v=V[u][i].v;
33             int w=V[u][i].w;
34             if(d[v]>d[u]+w){
35                 d[v]=d[u]+w;
36                 if(!vis[v]){
37                     vis[v]=1;
38                     Q.push(v);
39                 }
40             }
41         }
42     }
43 }
44 int main(void) 
45 {
46     int a,b,c;
47     while(scanf("%d%d",&n,&m)!=EOF)
48     {
49         for(int i=0;i<=n;i++) V[i].clear();
50         for(int i=0;i<m;i++){
51             scanf("%d%d%d",&a,&b,&c);        
52             V[a].push_back(node(b,c));
53             V[b].push_back(node(a,c));
54         }
55         scanf("%d%d",&a,&b);
56         spfa(a);
57         if(d[b]==inf) puts("-1");
58         else printf("%d\n",d[b]);
59     }
60     return 0;
61 }
View Code

 

 

 

posted @ 2013-10-27 12:05  heaventouch  阅读(125)  评论(0)    收藏  举报