Ideal Path,uva1599/hdu 3760(最短路中字典序最小的路径)

https://vjudge.net/problem/UVA-1599

给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色。求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小。一对结点间可能有多条边,一条边可能连接两个相同结点。输入保证结点1可以达到结点n。颜色为1~10^9的整数。

最短路+字典序

从终点开始倒着bfs,得到每个结点i到终点的最短距离d[i],然后直接从起点开始走,但是每次到达一个新结点时要保证d值恰好减1,如果有多条边的颜色字典序都是最小的,则记录所有这些边的终点,进行bfs。直到到达终点

贴上uva  WA,  TLE代码。

存在问题:

1. 没有搞清楚字典序列,所以WA了,这里的字典序列是将每个颜色作为最小单位。与平时的租个位比较不同

2.代码需要多个实例,没有用循环出现问题

3.使用了D来 求最短路径,超时了。

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <sstream>
#include <iostream>
using namespace std;
const int maxn=200005;
const int INF=0x3f3f3f3f;
struct Edge{
    int from,to,dist;
	int color;
};
struct HeapNode{
    int d,u;
    bool operator < (const HeapNode& rhs) const
    {
        return d>rhs.d;
    }
};
struct Dijkstra{
    int n,m;
    int d[maxn],p[maxn];
    bool done[maxn];
    vector<Edge> edges;
    vector<int> G[maxn];
    void init(int n)
    {
        this->n=n;
        for(int i=0;i<n;i++)G[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int dist,int color)
    {
        edges.push_back((Edge){from,to,dist,color});
        m=edges.size();
        G[from].push_back(m-1);
    }
    void dijkstra(int s)
    {
        priority_queue<HeapNode> Q;
        int u;
        HeapNode x;
        for(int i=0;i<n;i++)d[i]=INF;
        d[s]=0;
        memset(done,0,sizeof(done));
        Q.push((HeapNode){0,s});
        while(!Q.empty()){
            x=Q.top();Q.pop();
            u=x.u;
            if(done[u])continue;
            done[u]=true;
            for(int i=0;i<G[u].size();i++){
                Edge& e=edges[G[u][i]];
                if(d[e.to] > d[e.from]+e.dist){
                    d[e.to]=d[e.from]+e.dist;
                    p[e.to]=G[u][i];
                    Q.push((HeapNode){d[e.to],e.to});
                }
            }
        }
    }
    void print(int ibegin,int iend)
    {
   	   cout<<d[iend]<<":";
   	   stack<int> path;
   	   path.push(iend);
       while(iend!=ibegin)
	   {
	   	 Edge t=edges[p[iend]];
   	     path.push(t.from);
	     iend=t.from;		   
   	   };	
 
   	   int ecount=path.size();
       for(int i=0;i<ecount;i++)
	   {
	     if(i>0) cout<<"---";
	     cout<<path.top();
		 path.pop();
	   }
	   	
    }
    
    void printbycolor()
    {
   	   int idex=0;
   	   int in=d[0];
   	   bool isfirst=true;
   	   vector<int> curstart1,curstart2;
   	   curstart1.push_back(idex);
       while(in)
	   {
	   	 int imindex=1;
	   	 int imins=9999999;
	   	 in--;
		 curstart2.clear();
		 
	   	 for(int k=0;k<curstart1.size();k++)
	   	 {
	   	 	 idex=curstart1[k];
		   	 for(int i=0;i<G[idex].size();i++)
				{
					Edge& e=edges[G[idex][i]];
					if(d[e.to]==in) 
					if(e.color<imins)
					{
					   imins=e.color;
					   curstart2.clear();
					   curstart2.push_back(e.to);
					   
					}else if(e.color==imins)
					{
						curstart2.push_back(e.to);
					}
					
				}	   	 	
		 }
		 
         for(int k=0;k<curstart2.size();k++)
         {
         	curstart1.push_back(curstart2[k]);
		 }
		  //idex=imindex;	
		  //cout<<imindex<<" imindex "<<endl;
		  if(isfirst) 
		  isfirst=false;
		  else cout<<" ";		
		  cout<<imins;
		  		   
   	   };	
   	   cout<<endl;
    }
};
int n;
Dijkstra solver;
string inttostr(int t)
{
	 stringstream ss;
     ss<<t; 
     return ss.str();
}
int main()
{
    int m,a,b,c;
	while (~scanf("%d%d", &n, &m))
	{
        solver.init(n);
        while(m--){
            scanf("%d%d%d",&a,&b,&c);
            if(a==b) continue;
            a--;b--;
            solver.AddEdge(a,b,1,c);
            solver.AddEdge(b,a,1,(c));
        }
        solver.dijkstra(n-1);//注意,这里是开始点,所以的点从0开始 
        cout<<solver.d[0]<<endl;
        solver.printbycolor();
        
        //solver.print(0,1); 如果需要,可以打印路径
        

		//for(int i=0;i<n;i++) cout<<Map[i].size()<<endl;
		//memset(dp,-1,sizeof(dp));
		//dp[0]=1;
        //cout<<dfs(1)<<endl;
        
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qiang_____0712/article/details/84899957