字典序最小的最短路

来源:互联网 发布:ecshop支持的php版本 编辑:程序博客网 时间:2024/05/11 05:25

问题描述:

给出n和m,有n个点,m条双向边,1为起点,n为终点,每条边都有一个权值,经过每一条边的时间都为1,求从起点到终点既要时间最少,又要权值组成的序列的字典序最小的一条路径.

输入样例:

4 6
1 2 1
1 3 2
3 4 3
2 3 1
2 4 4 
3 1 1

输出样例:

2
1 3

限制范围:

50%,n<=100
100%,n<=100000,m<=200000

分析:

又是一道双关键字限制结果最优性的问题,此类问题一般思路就是枚举一个,计算最优另一个。
对于这道题,我们可以先用SPFA算出从终点开始到每个点的距离,然后从起点开始,每一步都选择权值最小的即可。其实也不是很复杂。

参考程序:

#include<cstdio>#include<algorithm>#include<set>#include<queue>#include<cstring>using namespace std;const int maxn=610000;const int INF=0x3f3f3f3f;struct Edge{int j,v,next;}e[maxn];int EdgeCnt=0;int d[maxn],a[maxn];bool inq[maxn];queue<int> Q;int n,m;void addedge(int u,int v,int w){int p=++EdgeCnt;e[p].j=v;e[p].v=w;e[p].next=a[u];a[u]=p;}int main(){freopen("ideal.in","r",stdin);freopen("ideal.out","w",stdout);scanf("%d%d",&n,&m);for (int i=0;i<m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);addedge(u,v,w);addedge(v,u,w);}memset(d,0x3f,sizeof(d));Q.push(n);inq[n]=true;d[n]=0;while (!Q.empty()){int u=Q.front();Q.pop();for (int p=a[u];p;p=e[p].next){int j=e[p].j;if (d[j]>d[u]+1){d[j]=d[u]+1;if (!inq[j]){inq[j]=true;Q.push(j);}}}inq[u]=false;}printf("%d\n",d[1]);set<int> now,next;now.insert(1);for (int dist=d[1]-1;dist>=0;dist--){int col=INF;for (set<int>::iterator u=now.begin();u!=now.end();u++){for (int p=a[*u];p;p=e[p].next){int j=e[p].j,v=e[p].v;if (d[j]==dist && v<=col){if (v<col){    col=v;    next.clear();    next.insert(j);    }else if (next.find(j)==next.end())next.insert(j);}}}printf("%d ",col);now=next;next.clear();}return 0;}


0 0