Ideal Path,uva1599/hdu 3760(最短路中字典序最小的路徑)
阿新 • • 發佈:2018-12-13
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; }