POJ 3767 I Wanna Go Home (dijkstra算法)
地址:http://poj.org/problem?id=3767
题目分析:
由于战争,一个商人想从城市1,回到自己的家城市2,其中城市1始终是由领导1,城市2始终由领导2,其中,商人回家的路中只能有一条路上连接由两个领导领导的城市,还有就是给出的路上双向的,也就是如果城市1能到城市2,那么城市2也同样能到城市1,这是关键。
由于这个题中从1类城市走到2类城市后就不能再回去,只能穿过一次,所以先存为双向路,后面再根据不同类型的城市,把双向路变为单向路
N个城市,城市编号为1,2,3,……N
M条路,路为双向路。 提供每条路的长度及端点城市编号,每两个城市之间直接连通的路最多一条。
这N个城市分为两个集合,部分属于集合1,部分属于集合2,提供每个城市所属的集合,现要求从城市1出发去城市2,要求途径的路中最多出现一条其两端城市不属于同一个集合 的路,求出符合该条件下的从城市1到城市2的最短路,若不存在符合条件的路,输出-1
注:数据中城市1必定属于集合1,城市2必定属于集合2
分析:由于城市1与城市2所属的集合固定,故在路径中必定有一条而且只能有一条路从属于集合 1的城市出发进入城市2,而定不会出现从集合2走向集合1的城市。
如此,M条路中凡是连接属于不同集合的城市的路为单向路,只能从集合1中的城市走向集合2, 在此基础上用Dijkstra算法求最短路即可。
核心算法 Dijkstra
思路:Dijkstra
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 #define inf 0xfffffff //定义inf为无穷大 6 #define size 610 7 int value[size][size]; //为true,则size为v0到size当前求得最短路径上的顶点 8 int d[size]; 9 int lead[size]; 10 bool visit[size];//为true,当且仅当size属于s,即已经求得最短路径上的顶点 11 int n,m; 12 void djk() 13 { 14 int x,y,z,tab,temp; 15 memset(visit,0,sizeof(visit)); //设初值 16 for(x=1;x<=n;x++) 17 d[x]=value[1][x]; //d[]存放1即(v0)到x即(v)的最短距离,初值为1到x的直接距离 18 d[1]=0; //1到1的距离为0 19 visit[1]=1; //1顶点并入s集 20 for(x=1;x<n;x++) //对于其余的n-1个顶点 21 { //开始主循环,每次求得1即(v0)到某个顶点v的最短路径,并将v并入s集 22 temp=inf; //当前所距离v0顶点的最近距离,设初值为∞ 23 for(y=1;y<=n;y++) //对所有顶点检查 24 { 25 if(!visit[y]&&d[y]<temp) //在s集之外的顶点中 26 { //找离1即v0最近的顶点y,并将其赋值给tab,距离赋给temp 27 temp=d[y]; 28 tab=y; 29 } 30 } 31 visit[tab]=true; //将tab并入s集 32 for(z=1;z<=n;z++) //根据新并入的顶点,更新不在s集的顶点到v0的距离和路径数组 33 { 34 if(!visit[z]&&d[z]>d[tab]+value[tab][z]) //z不属于s集且v0到v到z的距离<目前v0到z的距离 35 d[z]=d[tab]+value[tab][z]; //更新d[z] 36 } 37 } 38 if(d[2]==inf) 39 cout<<"-1\n"; //若不存在符合条件的路,输出-1 40 else 41 cout<<d[2]<<endl; 42 } 43 int main() 44 { 45 while(cin>>n) 46 { 47 if(n==0) 48 break; 49 int i,j,a,b,len; 50 cin>>m; 51 memset(lead,0,sizeof(lead)); 52 for(i=1;i<=n;i++) 53 for(j=1;j<=n;j++) 54 value[i][j]=inf; 55 for(i=1;i<=m;i++) 56 { 57 cin>>a>>b>>len; 58 value[a][b]=value[b][a]=len; 59 } 60 for(i=1;i<=n;i++) 61 cin>>lead[i]; 62 for(i=1;i<=n;i++) 63 { 64 for(j=1;j<=n;j++) 65 { 66 if(lead[i]!=lead[j]) 67 { 68 if(lead[i]==1&&lead[j]==2) 69 value[j][i]=inf; 70 else if(lead[i]==2&&lead[j]==1) 71 value[i][j]=inf; 72 } 73 } 74 } 75 djk(); 76 } 77 return 0; 78 } 79
代码2:
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define Max 0xfffffff 5 int m[610][610],p[610]; 6 bool vis[610]; 7 bool leader[610]; 8 int vexnum,arcnum; 9 void dijkstra() 10 { 11 int i,j,k,t,min; 12 memset(vis,0,sizeof(vis)); 13 for(i=1;i<=vexnum;++i) 14 p[i]=m[1][i]; 15 for(vis[1]=k=1;k<vexnum;++k){ 16 for(min=Max,i=1;i<=vexnum;++i) 17 if(!vis[i]&&min>p[i]){ 18 min=p[i]; 19 t=i; 20 } 21 vis[t]=1; 22 for(i=1;i<=vexnum;++i) 23 if(!vis[i]&&p[i]>min+m[t][i]) 24 p[i]=min+m[t][i]; 25 } 26 } 27 int main() 28 { 29 int i,j,t,a,b,w; 30 while(scanf("%d",&vexnum),vexnum&&scanf("%d",&arcnum)){ 31 for(i=1;i<=vexnum;++i) 32 for(j=1;j<=vexnum;++j) 33 m[i][j]=m[j][i]=Max; 34 for(i=0;i<arcnum;++i){ 35 scanf("%d%d%d",&a,&b,&w); 36 if(w<m[a][b]) 37 m[a][b]=m[b][a]=w; 38 } 39 for(i=1;i<=vexnum;++i){ 40 scanf("%d",&t); 41 leader[i]=t-1; 42 } 43 for(i=1;i<=vexnum;++i) 44 for(j=1;j<=vexnum;++j){ 45 if(leader[i]!=leader[j]){ 46 if(leader[i]) m[i][j]=Max; 47 else m[j][i]=Max; 48 } 49 } 50 dijkstra(); 51 if(p[2]<Max) printf("%d\n",p[2]); 52 else printf("-1\n"); 53 } 54 system("pause"); 55 return 0; 56 }