在网络通信中,经常需要求最短路径。但完全用最短路径传输有这样一个问题:如果最终在两个终端节点之间给出的最短路径只有一条。则在该路径中的任一个节点或链路出现故障时,信号传输将面临中断的危险。因此,对网络路由选择作了以下改进:
为任意两节点之间通信提供三条路径供其选择,即最短路径、第二最短路径和第三最短路径。
第一最短路径定义为:给定一个不含负回路的网络D={V,A,W},其中V={v1,v2,…,vn},A为边的集合,W为权的集合,设P1是D中最短(v1,vn)路。称P1为D中最短(v1,vn)路径,如果D中有一条(v1,vn)路,P2满足以下条件:
(1)P2≠P1;(2)D中不存在异于P1的路P,使得:
(3)W(P1)≤W(P)<W(P2)
则称P2为D的第二最短路径。
第三最短路径的定义为:设P2是D中第二最短(v1,vn)路径,如果D中有一条(v1,vn)路P3满足以下条件:
(1)P3≠P2并且P3≠P1;(2)D中不存在异于P1,P2的路P,使得:
(3)W(P2)≤W(P)<W(P3)
则称P3为D中第三最短路径。
现给定一有N个节点的网络,N≤30,求给定两点间的第一、第二和第三最短路径。
输入: n S T Max (每格数值之间用空格分隔)
M11 M12 … M1n
M21 M22 … M2n
… …
Mn1 Mn2 … Mnn
其中,n为节点数,S为起点,T为终点,Max为一代表无穷大的整数,Mij描述I到J的距离,若Mij=Max,则表示从I到J无直接通路,Mii=0。
输出:三条路径(从小到大输出),每条路径占一行,形式为:路径长度 始点…终点 (中间用一个空格分隔)
5 1 5 10000
0 1 3 10000 7
10000 0 1 10000 10000
10000 10000 0 1 4
10000 10000 10000 0 1
10000 1 10000 10000 0
4 1 2 3 4 5
5 1 3 4 5
6 1 2 3 5
/* 看完后以为是个k短路,然而路径不对 而且还没看到可以相同短 后来发现n很小,可以用搜索做 路径还是不对 改了好久才改对 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,len,topt,start,end,MAXN,first[500],m[50][50],ans[5],a[5][500],b[500],l[500]; struct edge { int from; int to; int val; int next; }e[50*50]; void add(int x,int y,int z) { topt++; e[topt].from=x; e[topt].to=y; e[topt].val=z; e[topt].next=first[x]; first[x]=topt; } int judge(int x) { int i=1,j=1; while(i<=l[x]&&j<=len) { if(b[j]==a[x][j]) { i++,j++; continue; } if(b[j]<a[x][i])return 1; return 0; } return len<l[x]; } void dfs(int now,int dis) { int i,j,k; if(dis>=ans[3])return; if(now==end) { if(dis<ans[1]||(dis==ans[1]&&judge(1))) { ans[3]=ans[2]; l[3]=l[2]; for(i=1;i<=l[2];i++) a[3][i]=a[2][i]; ans[2]=ans[1]; l[2]=l[1]; for(i=1;i<=l[1];i++) a[2][i]=a[1][i]; ans[1]=dis; l[1]=len; for(i=1;i<=len;i++) a[1][i]=b[i]; } else if(dis<ans[2]||(dis==ans[2]&&judge(2))) { ans[3]=ans[2]; l[3]=l[2]; for(i=1;i<=l[2];i++) a[3][i]=a[2][i]; ans[2]=dis; l[2]=len; for(i=1;i<=len;i++) a[2][i]=b[i]; } else if(dis<ans[3]||(dis==ans[3]&&judge(3))) { ans[3]=dis; l[3]=len; for(i=1;i<=len;i++) a[3][i]=b[i]; } return; } for(i=first[now];i;i=e[i].next) { int t=e[i].to; b[++len]=t; dfs(t,dis+e[i].val); len--; } } int main() { int i,j,k; scanf("%d%d%d%d",&n,&start,&end,&MAXN); for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&m[i][j]); for(i=1;i<=n;i++) for(j=n;j>=1;j--) if(m[i][j]!=0&&m[i][j]!=MAXN) add(i,j,m[i][j]); ans[1]=ans[2]=ans[3]=100; b[++len]=start; dfs(start,0); for(i=1;i<=3;i++) { printf("%d ",ans[i]); for(j=1;j<=l[i];j++) printf("%d ",a[i][j]); printf(" "); } return 0; } /*********************************************************//*分割线*/ /* 以下是由求k短路的思路作的 但貌似只能是严格的才行 而且路径好像输出不对...... */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,topt,start,end,MAXN,first[50],head[50],dis[50][5],f[50]; queue<int>q; struct edge { int from; int to; int val; int next; }e[50*50],ee[50*50]; void add(int x,int y,int z) { topt++; e[topt].from=x; e[topt].to=y; e[topt].val=z; e[topt].next=first[x]; first[x]=topt; ee[topt].from=y; ee[topt].to=x; ee[topt].val=z; ee[topt].next=head[y]; head[y]=topt; } void spfa() { int i,j,k; memset(dis,127/3,sizeof(dis)); q.push(start); dis[start][1]=0; f[start]=1; while(!q.empty()) { int u=q.front(); q.pop(); f[u]=0; for(i=first[u];i;i=e[i].next) { int t=e[i].to; if(dis[t][1]>dis[u][1]+e[i].val) { dis[t][3]=dis[t][2]; dis[t][2]=dis[t][1]; dis[t][1]=dis[u][1]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } if(dis[u][1]+e[i].val>dis[t][1]&&dis[t][2]>dis[u][1]+e[i].val) { dis[t][3]=dis[t][2]; dis[t][2]=dis[u][1]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } if(dis[u][1]+e[i].val>dis[t][2]&&dis[t][3]>dis[u][1]+e[i].val) { dis[t][3]=dis[u][1]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } if(dis[u][2]+e[i].val>dis[t][1]&&dis[t][2]>dis[u][2]+e[i].val) { dis[t][3]=dis[t][2]; dis[t][2]=dis[u][2]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } if(dis[u][2]+e[i].val>dis[t][2]&&dis[t][3]>dis[u][2]+e[i].val) { dis[t][3]=dis[u][2]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } if(dis[u][3]+e[i].val>dis[t][2]&&dis[t][3]>dis[u][3]+e[i].val) { dis[t][3]=dis[u][3]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } } } } void dfs(int now,int sum) { int i,j,k; if(sum==0)return; for(i=head[now];i;i=ee[i].next) { int t=ee[i].to; for(j=1;j<=3;j++) if(dis[t][j]+ee[i].val==sum) { dfs(t,dis[t][j]); break; } } printf("%d ",now); } int main() { int i,j,k; scanf("%d%d%d%d",&n,&start,&end,&MAXN); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { int x; scanf("%d",&x); if(x!=0&&x!=MAXN) add(i,j,x); } } spfa(); printf("%d ",dis[end][1]); printf("%d ",start); dfs(end,dis[end][1]); printf(" "); printf("%d ",dis[end][2]); printf("%d ",start); dfs(end,dis[end][2]); printf(" "); printf("%d ",dis[end][3]); printf("%d ",start); dfs(end,dis[end][3]); printf(" "); return 0; }