给一个n个顶点m条边 的无向图。每条边上都涂有一种颜色。求从结点1 到 结点n 的一条路径, 使得经过的边数尽量少,在此前提下, 经过的边的颜色的序列的字典序最小。
一对节点间可能有多条边,一条边可能连接两个相同结点。输入保证结点1 可以到达结点n。
这里用数组模拟链表来存储边。我们首先一次逆向bfs()构造分层网络。然后正向bfs每一步沿着分层步数递减的方向走,每次走的时候标记上在哪一层上走的哪一个颜色边
。这里绝对是个技巧。因为队列中出来的元素必然是兄弟结点全部出来完之后, 才会弹出这些兄弟结点的第一个作为接下来子树的根节点,所以用层数数组可以记录一层边
的颜色最小值, 即使他有多个堂兄弟。这样是完全可以理解的。
需要说明的一点是 构造分层网络时用到的vis数组,必须初始化为-1,否则存在bug,比如这组:
3 2
1 3 2
2 3 3
答案是:
1
2
才对。
但是a掉之后 即使vis置为0,也过了。
还有就是在找每个兄弟结点和孩子连边中的最小色彩值的时候。不知道为什么我把tmp设为足够大。然后每步更新tmp直至最小,这样提交结果却是wa。很是郁闷。
/*=============================================================================
#
# Author: liangshu - cbam
#
# QQ : 756029571
#
# School : 哈尔滨理工大学
#
# Last modified: 2015-11-18 19:54
#
# Filename: H.cpp
#
# Description:
# The people who are crazy enough to think they can change the world, are the ones who do !
=============================================================================*/
#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cctype>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int INF=400004;
int inq[INF];
int cnt[INF];
int low[INF];
int head[INF];
int n,m,c;
struct Edge
{
int next_edge,v,t,val;
} edge[INF];
void bfs1(int p){
memset(low, -1, sizeof(low));
low[p] = 0;
queue<int>q;
q.push(p);
while(!q.empty()){
int u = q.front();
if(u == 1){
return ;
}
q.pop();
for(int e = head[u]; e != -1; e = edge[e].next_edge){
if(low[edge[e].v] == -1 && edge[e].v != n){
low[edge[e].v] = low[u] + 1;
q.push(edge[e].v);
}
}
}
}
struct Node
{
int x;
Node(int x):x(x){
}
};
int ans[INF];
int vis[INF];
void bfs(int p){
memset(ans, 0, sizeof(ans));
memset(vis, 0, sizeof(vis));
queue<Node>q;
q.push(Node(p));
while(!q.empty()){
int e = q.front().x;
int tmp = -1;
q.pop();
for(int i = head[e]; i != -1; i = edge[i].next_edge){
if(low[edge[i].v] == low[e] - 1){
if(tmp == -1){
tmp = edge[i].val;
}
else{
tmp = min(edge[i].val, tmp);
}
}
}
int t = low[1] - low[e];
if(ans[t] == 0){
ans[t] = tmp;
}
else{
ans[t] = min(tmp, ans[t]);
}
for(int i = head[e]; i != -1; i = edge[i].next_edge){
if(!vis[edge[i].v] && edge[i].val == tmp && low[edge[i].v] == low[e] - 1){
q.push(edge[i].v);
vis[edge[i].v] = 1;
}
}
}
}
int main()
{
int x,y,z;
while(scanf("%d%d", &n, &m) != EOF)
{
memset(head,-1,sizeof(head));
for(int i=0; i<m; i++)
{
scanf("%d%d%d", &x, &y, &z);
if(x == y){
continue;
}
edge[i].next_edge=head[x];
edge[i].v=y;
edge[i].t=1;
edge[i].val = z;
head[x]=i;
edge[i+m].next_edge=head[y];
edge[i+m].v=x;
edge[i+m].t=1;
edge[i+ m].val = z;
head[y]=i+m;
}
bfs1(n);
bfs(1);
printf("%d\n%d", low[1], ans[0]);
for(int i = 1; i < low[1]; i++)
printf(" %d", ans[i]);
printf("\n");
}
return 0;
}
/*
4 5
1 2 3
2 3 345
3 4 2
4 2 2
1 3 1
*/