codevs 1062 路由选择

1062 路由选择

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
题目描述 Description

    在网络通信中,经常需要求最短路径。但完全用最短路径传输有这样一个问题:如果最终在两个终端节点之间给出的最短路径只有一条。则在该路径中的任一个节点或链路出现故障时,信号传输将面临中断的危险。因此,对网络路由选择作了以下改进:

为任意两节点之间通信提供三条路径供其选择,即最短路径、第二最短路径和第三最短路径。

    第一最短路径定义为:给定一个不含负回路的网络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,求给定两点间的第一、第二和第三最短路径。

输入描述 Input Description

输入:  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。

输出描述 Output Description

输出:三条路径(从小到大输出),每条路径占一行,形式为:路径长度 始点…终点  (中间用一个空格分隔)

样例输入 Sample Input

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

样例输出 Sample Output

4  1  2  3  4  5

5  1  3  4  5

6  1  2  3  5

数据范围及提示 Data Size & Hint

 

/*
看完后以为是个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("\n");
    }
    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("\n");

    printf("%d ",dis[end][2]);
    printf("%d ",start);
    dfs(end,dis[end][2]);
    printf("\n");
    
    
    printf("%d ",dis[end][3]);
    printf("%d ",start);
    dfs(end,dis[end][3]);
    printf("\n");
    
    return 0;
}

 

posted @ 2016-08-09 15:39  岂是蓬蒿人  阅读(254)  评论(0编辑  收藏  举报