UVA 1599 Ideal Path (理想路径)

来源:互联网 发布:判断数据上升趋势算法 编辑:程序博客网 时间:2024/03/28 20:39

【题意】

           给一个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构成一个层次图,直接能求出最短路径的长度,还为下面走的路径指明了方向,节约了代码 的时间复杂度和提供了准确的路径。




0 0