UVA 1599 Ideal Path (理想路径)

【题意】

           给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色。求从结点

         1到结点n的最短路径,在此前提下,经过边的颜色序列的字典序最小。一对结点间可能有多条边,一条边

        可能连接两个相同结点。输入保证结点1可以到达结点n。颜色为1~10^9的整数。


【分析】

 1.       本题是不错的bfs题,因为数据太大,如果直接找绝对超时。 

 2.       题目给的n小于等于100000,所以不能用邻接矩阵来保存,只能通过邻接表,用邻接表保存还方便进

       行遍历,用结构体保存邻接表,同时记录颜色的数值。

 3.       题目中无向图可能有自环和重边,自环可以在输入的时候省略掉,重边因为在输入的时候无法判断是

       否最短,所以保存下来,再用此点时,再进行遍历选取最短


【思路】


  1.       先倒着bfs,得到每一个结点i到终点的最少步数d[i],然后再从起点出发,每次到达一个新结点时保

          证d值恰好减少1,直到到达终点。

  2.       倒着bfs,保存每一个结点i到终点的最小步数,就相当于一个层次图,将于每个离终点相同的点放在 

          一个层次里,再从起点开始,一层一层的走,避免了1个点多次用到。

     

  3.       用queue和vector来进行层次图的路径的操作,用queue保存层次的点,vector保存本层次的对应的结

         构体的坐标,中间有太多细节需要考虑。每走一点清一次queue,每走一层清空一次vector。标记数组记录

         某点是否走过,避免重走。

 4.        因为事先求出了每点i到终点的最短路径d[i],所以不用保存路径,只需求出当前步中最小的颜色的数

         值,就是最优的解,直接输出就行。


【代码】

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
const int MAXN=100000+5;
const int MAXM=200000+5;
const int INF=0x3f3f3f3f;
struct node
{
    int x;
    int color;
    int next;
} G[MAXM*2];
int head[MAXN],d[MAXN];
bool book[MAXN];
int n,m,cnt;

void Addedge(int a,int b,int c)
{
    G[cnt].x=b;
    G[cnt].color=c;
    G[cnt].next=head[a];
    head[a]=cnt++;
}

void Bfs1()
{
    queue<int>p;
    d[n]=0;
    p.push(n);
    while(!p.empty())
    {
        int x=p.front();
        p.pop();
        if(x==1)
        {
            printf("%d\n",d[x]);
            return ;
        }
        for(int i=head[x]; i!=-1; i=G[i].next)
        {
            int k=G[i].x;
            if(d[k]!=-1)
                continue;
            p.push(k);
            d[k]=d[x]+1;
        }
    }
    return ;
}

void Bfs2()
{
    queue<int>p;     // 保存下一步的点
    vector<int>Vec;  // 保存结构体的下坐标
    p.push(1);
    book[1]=true;
    int color=INF;
    while(!p.empty()||Vec.size())
    {
        if(p.empty())
        {
            int len=Vec.size();
            for(int i=0; i<len; i++)
            {
                int k=Vec[i];
                int x=G[k].x;
                if(G[k].color==color&&!book[x])
                {
                    if(x==n)
                    {
                        printf("%d\n",color);
                        return ;
                    }
                    p.push(x);
                    book[x]=true;
                }
            }
            printf("%d ",color);
            Vec.clear();
            color=INF;
        }
        int k=p.front();
        p.pop();
        for(int i=head[k]; i!=-1; i=G[i].next)
        {
            int x=G[i].x;
            if(d[k]-d[x]==1&&G[i].color<=color)
            {
                Vec.push_back(i);
                color=G[i].color;
            }
        }
    }
    return ;
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(head,-1,sizeof(head));
        memset(d,-1,sizeof(d));
        memset(book,false,sizeof(book));
        cnt=0;
        int a,b,c;
        for(int i=0; i<m; i++)
        {
            scanf("%d %d %d",&a,&b,&c);
            Addedge(a,b,c);
            Addedge(b,a,c);
        }
        Bfs1();
        Bfs2();
    }
    return 0;
}

【收获】

      本题是到不错的bfs题,考了很多内容,queue、vector、邻接表、双向bfs,使一个大数据的题,得到很好  的解决。

        尤其是倒着bfs构成一个层次图,直接能求出最短路径的长度,还为下面走的路径指明了方向,节约了代码 的时间复杂度和提供了准确的路径。




猜你喜欢

转载自blog.csdn.net/disparity_cjk/article/details/52918080
今日推荐