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),分别代表起点和终点。
每组数据第一行包含两个正整数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
/*
题意:
中文...
最短路径:
直接模板题.
*/
题意:
中文...
最短路径:
直接模板题.
*/
以下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 }
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 }
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 }
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 }
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 }

浙公网安备 33010602011771号