您的位置:首页 > 其它

UVA 1599 Ideal Path (理想路径)

2016-10-25 09:45 369 查看
【题意】

           给一个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
=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构成一个层次图,直接能求出最短路径的长度,还为下面走的路径指明了方向,节约了代码 的时间复杂度和提供了准确的路径。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: