CF1184E2

题目大意:
给一个带权无向图。定义\(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\n",ans[i]);
	return 0;
}
posted @ 2020-03-22 21:31  优秀的渣渣禹  阅读(132)  评论(0编辑  收藏  举报