先倒着从n bfs一遍求出bfs树每层的节点,然后从1贪心的走回来就行了
这个贪心用两个queue即可实现。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define rep(i , n) for(int i = 0 ;i<(int)n;i++) #define rep1(i,x,y) for(int i = (int)x ; i<=(int)y;i++) const int N = 1e5 + 100; const int M = 4e5 + 100; struct node{ int u , v , c; node(int u = 0 ,int v = 0 , int c = 0):u(u),v(v),c(c){} }e[M]; int head[N] , nex[M] , cnt ; int n, m; void init(){ cnt = 0; rep1(i,1,n) head[i] = -1; } void add_edge(int u ,int v , int c){ e[++cnt] = node(u , v , c); nex[cnt] = head[u]; head[u] = cnt; } int d[N]; void bfs(){ int q[N] , front = 0, rear = 0; rep1(i , 1 , n) d[i] = -1; d[n] = 0; q[front] = n; while(front <= rear){ int u = q[front++]; for(int i = head[u] ; i!= -1 ; i = nex[i]){ node te = e[i]; if(d[te.v] == -1){ d[te.v] = 1 + d[u]; q[++rear] = te.v; } } } } int ans[N] , done[N]; void bfs2(){ queue<int> q[3]; rep1(i ,1 , n) done[i] = -1; int now = 0, pre = 1; q[pre].push(1); int flag= 0; while(d[q[pre].front()] > 0){ ++flag; int min_ = 1e9 + 100; while(!q[pre].empty()){ int u = q[pre].front(); q[pre].pop(); for(int i = head[u] ; i!=-1 ; i = nex[i]){ node te = e[i]; if(d[te.v] + 1 != d[u]) continue; if(te.c > min_) continue; if(te.c < min_){ while(!q[2].empty()) q[2].pop(); min_ = te.c; } q[2].push(te.v); } } while(!q[2].empty()){ int u = q[2].front(); q[2].pop(); if(done[u] != flag){ done[u] = flag; q[now].push(u); } } swap(pre, now); ans[flag] = min_; } printf("%d\n",d[1]); for(int i = 1 ; i<=flag ; i++){ if(i > 1) printf(" "); printf("%d",ans[i]); } printf("\n"); } int main() { int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); init(); rep(i,m){ int u , v, c; scanf("%d %d %d",&u,&v,&c); add_edge(u , v , c); add_edge(v , u , c); } bfs(); bfs2(); } return 0; }
时间: 2024-10-12 07:48:36