• Uva 1599 Ideal path


    New labyrinth attraction is open in New Lostland amusement park. The labyrinth consists of n rooms connected by m passages. Each passage is colored into some color ci . Visitors of the labyrinth are dropped from the helicopter to the room number 1 and their goal is to get to the labyrinth exit located in the room number n. Labyrinth owners are planning to run a contest tomorrow. Several runners will be dropped to the room number 1. They will run to the room number n writing down colors of passages as they run through them. The contestant with the shortest sequence of colors is the winner of the contest. If there are several contestants with the same sequence length, the one with the ideal path is the winner. The path is the ideal path if its color sequence is the lexicographically smallest among shortest paths. Andrew is preparing for the contest. He took a helicopter tour above New Lostland and made a picture of the labyrinth. Your task is to help him find the ideal path from the room number 1 to the room number n that would allow him to win the contest. Note: A sequence (a1, a2, . . . , ak) is lexicographically smaller than a sequence (b1, b2, . . . , bk) if there exists i such that ai < bi , and aj = bj for all j < i.

    Input

    The input file contains several test cases, each of them as described below. The first line of the input file contains integers n and m — the number of rooms and passages, respectively (2 ≤ n ≤ 100000, 1 ≤ m ≤ 200000). The following m lines describe passages, each passage is described with three integer numbers: ai , bi , and ci — the numbers of rooms it connects and its color (1 ≤ ai , bi ≤ n, 1 ≤ ci ≤ 109 ). Each passage can be passed in either direction. Two rooms can be connected with more than one passage, there can be a passage from a room to itself. It is guaranteed that it is possible to reach the room number n from the room number 1.

    Output

    For each test case, the output must follow the description below. The first line of the output file must contain k — the length of the shortest path from the room number 1 to the room number n. The second line must contain k numbers — the colors of passages in the order they must be passed in the ideal path.

    Sample Input

    4 6

    1 2 1

    1 3 2

    3 4 3

    2 3 1

    2 4 4

    3 1 1

    Sample Output

    2 1 3

    题解:

    有两种方法:

    第一种:先用BFS处理出没一点到1号店的最短距离,然后再BFS寻找字典序最小的;

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    const int maxn=1e5+10;
    int n,m,i,j,k,u,v,w;
    int first[maxn],pre[maxn],q[maxn],dis[maxn],vis[maxn];
    struct edge{
        int x,y,c;
        int nxt;
    } edge[maxn<<2];
    
    void Init()
    {
    	memset(first,0,sizeof(first));
        memset(pre,0,sizeof(pre));
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        while(cin>>n>>m)
    	{
    		Init();
            for(i=1,j=0;j<m;j++,i+=2)
    		{
                cin>>u>>v>>w;
                edge[i].x=u; edge[i].y=v; edge[i].c=w;
                edge[i+1].x=v; edge[i+1].y=u; edge[i+1].c=w;
    
                edge[i].nxt=first[u]; first[u]=i;
                edge[i+1].nxt=first[v]; first[v]=i+1;
            }
            q[0]=n; 
    		int l=0,r=1; pre[1]=pre[0]=0;
            dis[n]=0; vis[n]=1;
            while(l<r)
    		{
                int x=q[l++];
                for(j=first[x];j;j=edge[j].nxt)
    			{
                    int V=edge[j].y,W=edge[j].c;
                    if(vis[V])
    				{
                        if(dis[V]==dis[x]+1)
    					{ 
                            int e1=pre[V],e2=j;
                            while(e1!=e2 && edge[e1].c==edge[e2].c) e1=pre[edge[e1].x],e2=pre[edge[e2].x];
                            if(edge[e1].c>edge[e2].c) pre[V]=j;
                        }
                    }
    				else
    				{
                        vis[V]=1; pre[V]=j;
                        dis[V]=dis[x]+1;
                        q[r++]=V;
                    }
                }
            }
            cout<<dis[1]<<endl;
            for(int e=pre[1],i=0;i<dis[1];i++)
    		{
                if(i) cout<<' ';
                cout<<edge[e].c;
                e=pre[edge[e].x];
            }
            cout<<endl;
        }
        return 0;
    }
    

      我主要说第二种:一个BFS就可一解决问题:

    我们可以倒着处理;用邻接表存边的信息;pre[i]表示i前面的那条边,dis[i]表示i到n号点的最短距离;vis[i]代表i点是否访问过;

    我对于每一个点的子节点,判断其是否被访问过,如果没被访问过,则dis[v]=dis[u]+1; pre[v]=v和u相连的边的编号,标记为访问过,然后该点入队;

    如被访问过:则如果当前路径长度与已有的v点路径长度相等,则从该点分别往两条路上回溯pre数组,直到其父亲节点相同,或者出现了一条边的颜

    色与另一条边的颜色不同,则将其pre[v]更新为颜色小的那条边即可,直到访问到1号节点;

    参考代码为:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    const int maxn=1e5+10;
    int n,m,k,u,v,w,tot;
    int first[maxn],pre[maxn],q[maxn],dis[maxn],vis[maxn];
    struct edge{
        int U,V,W,nxt;
    } edge[maxn<<2];
    
    void Init()
    {
    	memset(first,-1,sizeof first);
        memset(pre,0,sizeof pre);
        memset(dis,0,sizeof dis);
        memset(vis,0,sizeof vis);
        tot=1;
    }
    
    void addedge(int u,int v,int w)
    {
    	edge[tot].U=u; 
    	edge[tot].V=v; 
    	edge[tot].W=w;
    	edge[tot].nxt=first[u]; 
    	first[u]=tot++;
    }
    
    void search()
    {	
    	q[0]=n; 
    	int l=0,r=1;
        dis[n]=0; vis[n]=1;
        while(l<r)
    	{
            int u=q[l++];
            for(int j=first[u];j;j=edge[j].nxt)
    		{
                int V=edge[j].V,W=edge[j].W;
                if(vis[V])
    			{
                    if(dis[V]==dis[u]+1)
    				{ 
                        int x=pre[V],y=j;
                        while(x!=y && edge[x].W==edge[y].W) x=pre[edge[x].U],y=pre[edge[y].U];
                        if(edge[x].W>edge[y].W) pre[V]=j;
                    }
                }
    			else
    			{
                    vis[V]=1; pre[V]=j;
                    dis[V]=dis[u]+1;
                    q[r++]=V;
                }
            }
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        while(cin>>n>>m)
    	{
    		Init();
    		for(int i=0;i<m;i++) 
    		{
    			cin>>u>>v>>w;
    			addedge(u,v,w);
    			addedge(v,u,w);
    		}
            search();
            cout<<dis[1]<<endl;
            for(int e=pre[1],i=0;i<dis[1];i++)
    		{
                if(i) cout<<' ';
                cout<<edge[e].W;
                e=pre[edge[e].U];
            }
            cout<<endl;
        }
        return 0;
    }
    

      

  • 相关阅读:
    「SOL」工厂选址(BZOJ)
    「NOTE」数论小札
    Flask实现简单的群聊和单聊
    python基础总结
    基于Flask和百度AI实现与机器人对话
    django创建路径导航
    django中权限控制到按钮级别
    django中非菜单权限的归属
    MongoDB的增删改查
    jQuery于js的区别和联系
  • 原文地址:https://www.cnblogs.com/csushl/p/9409972.html
Copyright © 2020-2023  润新知