小学生求助:本题RE
查看原帖
小学生求助:本题RE
430133
liangbob楼主2023/9/27 12:20

rt,在 AT 上仅过了样例,其余均 RE。

思路,采用 Kruskal 的思想:

  1. 对边进行排序

  2. 对于每个查询,二分查找第一个比他大的数的下标 kk。

  3. 判断在前 k−1k - 1 条边中,加入查询的边后是否存在环(用并查集来判断)

#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
#define endl '\n'
#define IL inline
using namespace std;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;

IL 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;
}

void write(int x)
{
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

struct edge
{
	int u, v, w;
};

edge e[N];
int ew[N];
map <int, int> fa[N];

int find(int u, int x)
{
	return fa[u][x] == x ? x : fa[u][x] = find(u, fa[u][x]);
}

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

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n, m, q;
	cin >> n >> m >> q;
	for(int i = 1;i <= m;i++)
	{
		cin >> e[i].u >> e[i].v >> e[i].w;
		ew[i] = e[i].w;
	}
	sort(e + 1, e + m + 1, cmp);
	sort(ew + 1, ew + m + 1);
	for(int i = 1;i <= n;i++)
	{
		fa[0][i] = i;
	}
	int cnt = 0;
	for(int i = 1;i <= m;i++)
	{
		fa[i] = fa[i - 1];
		if(cnt < n)
		{
			int s1 = find(i, e[i].u);
			int s2 = find(i, e[i].v);
			if(s1 != s2)
			{
				fa[i][s1] = s2;
				cnt++;
			}
		}
	}
	for(int i = 1;i <= q;i++)
	{
		int x, y, z;
		cin >> x >> y >> z;
		int rk = upper_bound(ew + 1, ew + m + 1, z) - ew;
		if(rk == 1)
		{
			cout << "Yes" << endl;
			continue;
		}
		if(rk > n)
		{
			cout << "No" << endl;
			continue;
		}
		if(find(rk - 1, x) == find(rk - 1, y))
		{
			cout << "No" << endl;
			continue;
		}
		cout << "Yes" << endl;
	}
	return 0;
}
2023/9/27 12:20
加载中...