社区讨论

p4180kruskal+倍增lca80ptsWA#8#10求调(码风较为舒适)

P4180[BJWC2010] 严格次小生成树参与者 3已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@lo1np1tf
此快照首次捕获于
2023/10/23 00:01
2 年前
此快照最后确认于
2023/11/03 00:44
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,ans,tot,lg,sec;

struct EDGE{
	int ver,nxt,w;
}edge[6 * 100005];
int head[100005];

struct node{
	int from,to,w;
}e[6 * 100005];

int d[100005],fa[100005][20],f[100005],maxn[100005][20],s[100005][20];

bool used[6 * 100005];

int read(){
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
	return x * f;
}

bool cmp(node x,node y){
	return x.w < y.w;
}

int get(int x){
	if(f[x] == x)
		return x;
	return f[x] = get(f[x]);
}

void add(int u,int v,int w){
	edge[++tot].ver = v;
	edge[tot].w = w;
	edge[tot].nxt = head[u];
	head[u] = tot;
}

void kruskal(){
	for(int i = 1;i <= n;i++)
		f[i] = i;
	for(int i = 1;i <= m;i++){
		int x = e[i].from;
		int y = e[i].to;
		int z = e[i].w;
		int r1 = get(x),r2 = get(y);
		if(r1 != r2){
			f[r1] = r2;
			ans += z;
			used[i] = true;
			add(x,y,z);
			add(y,x,z);
		}
	}
}

void dfs(int x,int dep){
	d[x] = dep;
	for(int i = head[x];i;i = edge[i].nxt){
		int y = edge[i].ver;
		int w = edge[i].w;
		if(!d[y]){
			fa[y][0] = x;
			maxn[y][0] = w;
			for(int j = 1;j <= lg;j++){
				fa[y][j] = fa[fa[x][j - 1]][j - 1];
				int big = max(maxn[y][j - 1],maxn[fa[y][j - 1]][j - 1]);
				int sma = min(maxn[y][j - 1],maxn[fa[y][j - 1]][j - 1]);
				if(big > maxn[y][j]){
					s[y][j] = maxn[y][j];
					maxn[y][j] = big;
				}
				if(sma < maxn[y][j] && sma > s[y][j])
					s[y][j] = sma;
			}
				
			dfs(y,dep + 1);
			
		}
	}
}

int lca(int x,int y,int z){
	int firs = 0,seco = 0;
	if(d[x] < d[y])
		swap(x,y);
	for(int i = lg;i >= 0;i--)
		if(d[fa[x][i]] >= d[y]){
			if(maxn[x][i] > firs){
				seco = firs,firs = maxn[x][i];
				if(s[x][i] > seco)
					seco = s[x][i];
			}
				
			else if(maxn[x][i] < firs && maxn[x][i] > seco){
				seco = maxn[x][i];
			}
				
			x = fa[x][i];
		}
	if(x == y){
		if(firs != z)
			return firs;
		return seco;
	}
		
	for(int i = lg;i >= 0;i--){
		if(fa[x][i] != fa[y][i]){
			if(maxn[x][i] > firs){
				seco = firs,firs = maxn[x][i];
				if(s[x][i] > seco)
					seco = s[x][i];
			}
				
			else if(maxn[x][i] < firs && maxn[x][i] > seco){
				seco = maxn[x][i];
			}
			
			if(maxn[y][i] > firs){
				seco = firs,firs = maxn[y][i];
				if(s[y][i] > seco)
					seco = s[y][i];
			}
				
			else if(maxn[y][i] < firs && maxn[y][i] > seco){
				seco = maxn[y][i];
			}
			
			x = fa[x][i],y = fa[y][i];
		}
	}
	if(maxn[x][0] > firs)
		seco = firs,firs = maxn[x][0];
	else if(maxn[x][0] > seco)
		seco = maxn[x][0];
	if(maxn[y][0] > firs)
		seco = firs,firs = maxn[y][0];
	else if(maxn[y][0] > seco)
		seco = maxn[y][0];
	if(firs < z)
		return firs;
	return seco;
}

signed main(){
	n = read(),m = read();
	lg = log(n) / log(2) + 1;
	for(int i = 1;i <= m;i++){
		e[i].from = read();
		e[i].to = read();
		e[i].w = read();
		
	}
	sec = 1e15;
	sort(e + 1,e + m + 1,cmp);
	
	kruskal();
	
	dfs(1,1);
	
	for(int i = 1;i <= m;i++){
		if(used[i])
			continue;
		int x = e[i].from,y = e[i].to,z = e[i].w;
		int change = lca(x,y,z);
		//printf("%d %d %d\n%d\n",x,y,z,change);
		if(change)
			sec = min(sec,ans + z - change);
	}
	printf("%d\n",sec);
	return 0;
}

回复

7 条回复,欢迎继续交流。

正在加载回复...