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;
}