rt,在 AT 上仅过了样例,其余均 RE。
思路,采用 Kruskal 的思想:
对边进行排序
对于每个查询,二分查找第一个比他大的数的下标 k。
判断在前 k−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;
}