社区讨论

蒟蒻求助严格次小生成树,洛谷TLE 80pts,Loj WA 82pts

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

讨论操作

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

当前回复
0 条
当前快照
1 份
快照标识符
@lo8be49z
此快照首次捕获于
2023/10/27 15:51
2 年前
此快照最后确认于
2023/10/27 15:51
2 年前
查看原帖
我的思路是建出最小生成树后,用倍增跳来维护最大值和次大值,然后去找环上最大的点,Subtask 1 的两个点均已过,但还是 WA & TLE /kk
有没有大佬帮忙康康 /kel
CPP
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#define int long long
#define REP(i, x, y) for(int i = x; i < y; i++)
#define rep(i, x, y) for(int i = x; i <= y; i++)
#define PER(i, x, y) for(int i = x; i > y; i--)
#define per(i, x, y) for(int i = x; i >= y; i--)
#define lc (k << 1)
#define rc (k << 1 | 1)
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;
}

const int LOG = 20;
const int N = 100005;
const int M = 300005;
int n, m;
struct node{
	int u, v, w;
}ed[M];
struct node2{
    int v, w;
};
vector <node2> g[N];
int val[N], sum, maxn1_path, maxn2_path, in_tree[N], father[N], fa[N][LOG], maxn1[N][LOG], maxn2[N][LOG], dep[N], b[N];
bool cmp(node xx, node yy)
{
	if(xx.w == yy.w) return xx.u < yy.u;
	else return xx.w < yy.w;
}
bool cmp2(int xx, int yy)
{
	return xx > yy;
}
void get_max(int &m1, int &m2, int a1, int a2, int b1, int b2)
{
	if(a1 > b1)
	{
		m1 = a1;
		m2 = max(b1, a2);
	}
	else if(a1 == b1)
	{
		m1 = a1;
		m2 = max(b1, b2);
	}
	else
	{
		m1 = b1;
		m2 = max(a1, b2);
	}
	return;
}
int find(int x)
{
	if(x == father[x])
	{
		return x;
	}
	else
	{
		return x = find(father[x]);
	}
}
void dfs(int x)
{
	for(int i = 0; i < g[x].size(); i++)
	{
		int xx = g[x][i].v;
		int w = g[x][i].w;
		if(!b[xx])
		{
			b[xx] = 1;
			dep[xx] = dep[x] + 1;
			fa[xx][0] = x;
			val[xx] = w;     
            maxn1[xx][0] = val[x];
			dfs(xx);
		}
	}
}
void LCA(int x, int y)
{
	maxn1_path = -1, maxn2_path = -1;
    if(val[x] > val[y])
    {
        maxn1_path = val[x];
        maxn2_path = val[y];
    }
    else if(val[x] == val[y])
    {
        maxn1_path = val[x];
    }
    else
    {
        maxn1_path = val[y];
        maxn2_path = val[x];    
    }
//    cout<<"???"<<maxn1_path<<" "<<endl;
	if(dep[x] < dep[y])
	{
		swap(x, y);
	}
	int t = dep[x] - dep[y];
	for(int i = LOG - 1; i >= 0; i--)
	{
		if((t >> i) & 1)
		{
            if(maxn1_path > maxn1[x][i])
            {
                maxn2_path = max(maxn2_path, maxn1[x][i]);
            }
            else if(maxn1_path == maxn1[x][i])
            {
                maxn2_path = max(maxn2_path, maxn2[x][i]);
            }
            else
            {
                maxn2_path = max(maxn1_path, maxn2[x][i]); 
                maxn1_path = maxn1[x][i];
            }	
            x = fa[x][i];
		}
	}
	if(x == y)
	{
		return;
	}
	for(int i = LOG - 1; i >= 0; i--)
	{
		if(fa[x][i] != fa[y][i])
		{
            if(maxn1_path > maxn1[x][i])
            {              
                maxn2_path = max(maxn2_path, maxn1[x][i]);
            }
            else if(maxn1_path == maxn1[x][i])
            {
                maxn2_path = max(maxn2_path, maxn2[x][i]);
            }
            else
            {  
                maxn2_path = max(maxn1_path, maxn2[x][i]); 
                maxn1_path = maxn1[x][i];
            }		
			x = fa[x][i];
            if(maxn1_path > maxn1[y][i])
            {
                maxn2_path = max(maxn2_path, maxn1[y][i]);
            }
            else if(maxn1_path == maxn1[y][i])
            {
                maxn2_path = max(maxn2_path, maxn2[y][i]);
            }
            else
            {
                maxn2_path = max(maxn1_path, maxn2[y][i]); 
                maxn1_path = maxn1[y][i];
            }	
			y = fa[y][i];
		}
	}
	return;//由于把边权挂在了儿子上,所以不要 LCA 的最大值与次大值!
}
signed main()
{
	scanf("%lld%lld", &n, &m);
	rep(i, 1, m)
	{
		int x, y, z;
		x = read(); y = read(); z = read();
        if(x == y) continue;
		ed[i].u = x; ed[i].v = y; ed[i].w = z;
	}
	for(int i = 1; i <= n; i++)
	{
		father[i] = i;
	}
	sort(ed + 1, ed + m + 1, cmp);
	for(int i = 1; i <= m; i++)
	{
		int fu = find(ed[i].u);
		int fv = find(ed[i].v);
		if(fu != fv)
		{
			father[fv] = fu;
			g[ed[i].u].push_back({ed[i].v, ed[i].w});
			g[ed[i].v].push_back({ed[i].u, ed[i].w});
			sum += ed[i].w;
			in_tree[i] = 1;
		}
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 0; j <= LOG - 1; j++)
		{
			maxn1[i][j] = maxn2[i][j] = -1;
		}
	}
	b[1] = 1;
	dep[1] = 1;
	dfs(1);
	for(int i = 1; i <= LOG - 1; i++)
	{
		for(int x = 1; x <= n; x++)
		{
			fa[x][i] = fa[fa[x][i - 1]][i - 1];
			int temp = fa[x][i - 1];
			get_max(maxn1[x][i], maxn2[x][i], maxn1[x][i - 1], maxn2[x][i - 1], maxn1[temp][i - 1], maxn2[temp][i - 1]);
//			cout << i << " " << x << " " << fa[x][i] << " " << maxn1[x][i] << " " << maxn2[x][i] << endl;
		}		
	}
//	cout << sum << endl;
	int ans = 99999999999999999;
	for(int i = 1; i <= m; i++)
	{
		if(!in_tree[i])
		{
			int x = ed[i].u;
			int y = ed[i].v;
			int w = ed[i].w;
			LCA(x, y);
			if(maxn1_path == w)
			{
				if(maxn2_path != -1)
					ans = min(ans, sum - maxn2_path + w); 
			}
			else if(maxn1_path != -1)
			{
				ans = min(ans, sum - maxn1_path + w);
			}
 //           cout << x << " " << y << " " << w << " " << maxn1_path << " " << maxn2_path<<endl;
		}
	}
	printf("%lld", ans);
	return 0;
}

回复

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

正在加载回复...