题目大意:
给一个带权无向图。定义(E_{max} (c_i)) 是把第 (i) 条边的边权最大修改成多大,使得它可能出现在最小生成树中。求 (E_{max}(c_i)) ,保证最小生成树唯一。
因为最小生成树唯一,所以还是有一个易证的结论:一条非树边的答案为对应最小生成树的链上最大值。
#define B cout << "BreakPoint" << endl;
#define O(x) cout << #x << " " << x << endl;
#define O_(x) cout << #x << " " << x << " ";
#define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#define LL long long
const int inf = 1e9 + 9;
const int N = 1e6 + 5;
using namespace std;
inline int read() {
int s = 0,w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-')
w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
int n,m;
struct Tree{
struct edge { int to,nxt,w,id; }e[N << 1];int head[N],cnt;
void add(int u,int v,int w,int id) { e[++cnt].w = w,e[cnt].id = id,e[cnt].to = v,e[cnt].nxt = head[u];head[u] = cnt; }
void add_edge(int u,int v,int w,int id) { add(u,v,w,id),add(v,u,w,id); }
int dep[N],up[N],f[N][20],maxx[N][20];
void dfs(int u,int fa){
dep[u] = dep[fa] + 1,f[u][0] = fa;
for(int i = head[u];i;i = e[i].nxt){
int v = e[i].to;
if(v == fa) continue;
maxx[v][0] = e[i].w,up[v] = e[i].id;
dfs(v,u);
}
}
void init(){
dfs(1,0);
for(int j = 1;j < 20;j++)
for(int i = 1;i <= n;i++){
f[i][j] = f[f[i][j - 1]][j - 1];
maxx[i][j] = max(maxx[i][j - 1],maxx[f[i][j - 1]][j - 1]);
}
}
pair<int,int> LCA(int u,int v){
int ans = 0;
if(dep[u] < dep[v]) swap(u,v);
int h = dep[u] - dep[v];
for(int i = 0;i < 20;i++) if(h & (1 << i)) ans = max(ans,maxx[u][i]),u = f[u][i];
if(u == v) return make_pair(u,ans);
for(int i = 19;~i;i--) if(f[u][i] ^ f[v][i]) ans = max(ans,max(maxx[u][i],maxx[v][i])),u = f[u][i],v = f[v][i];
return make_pair(f[u][0],max(ans,max(maxx[u][0],maxx[v][0])));
}
}T;
struct edge{
int u,v,w,id;
friend bool operator < (edge a,edge b) { return a.w < b.w; }
}e[N];
bool vis[N];
int fa[N],ans[N];
int find(int u) { return fa[u] == u ? u : fa[u] = find(fa[u]); }
int main(){
n = read(),m = read();
for(int i = 1;i <= m;i++) e[i].u = read(),e[i].v = read(),e[i].w = read(),e[i].id = i;
sort(e + 1,e + 1 + m);
for(int i = 1;i <= n;i++) fa[i] = i;
for(int i = 1;i <= m;i++){
int x = find(e[i].u),y = find(e[i].v);
if(x ^ y){
fa[x] = y;
T.add_edge(e[i].u,e[i].v,e[i].w,e[i].id);
vis[i] = 1;
}
}
T.init();
for(int i = 1;i <= m;i++)
if(!vis[i]){
auto w = T.LCA(e[i].u,e[i].v);
ans[e[i].id] = w.second;
}
for(int i = 1;i <= m;i++) if(ans[i]) printf("%d
",ans[i]);
return 0;
}