概述
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int N=501000;
int n,m,u[N],v[N],w[N],f[N],p[N],qrcase[N],T,wa[N];
int Q,k,id,x,maxw;
vector<int> eg[N];
vector<PII> qw[N];
int nxt1[N], nxt2[N];
int find1(int now){
if (nxt1[now]==now) return now;
return nxt1[now]=find1(nxt1[now]);
}
int find2(int now){
if (qrcase[now]!=T){qrcase[now]=T; nxt2[now]=nxt1[now];}
if (nxt2[now]==now) return now;
return nxt2[now]=find2(nxt2[now]);
}
int main() {
maxw=0;
scanf("%d%d",&n,&m);
for (int i=1; i<=m; i++){
scanf("%d%d%d", u+i, v+i, w+i);
eg[w[i]].push_back(i);
maxw=max(maxw, w[i]);
}
scanf("%d", &Q);
for (int i=0; i<Q; i++){
scanf("%d", &id);
for (int j=0; j<id; j++){
scanf("%d", &x);
qw[w[x]].push_back(mp(i, x));
}
}
memset(wa, 0, sizeof(wa));
for (int i=1; i<=n; i++){
nxt1[i]=i;
}
T=0;
for (int i=1; i<=maxw; i++){
sort(qw[i].begin(), qw[i].end());
for (int j=0; j<qw[i].size(); j++){
if (j==0 || qw[i][j].first!=qw[i][j-1].first) T++;
int x=u[qw[i][j].second], y=v[qw[i][j].second];
if (find2(x)==find2(y)){
wa[qw[i][j].first]=true;
}
nxt2[find2(y)]=nxt2[find2(x)];///nxt2[y]=x;
}
for (int j=0; j<eg[i].size(); j++){
int x=find1(u[eg[i][j]]); int y=find1(v[eg[i][j]]);
nxt1[find1(y)]=find1(x);
}
}
for (int i=0; i<Q; i++){
if (wa[i]) printf("NOn"); else printf("YESn");
}
}
两个注意点
第一点是原理,按照边权值由小到大的顺序,处理每个query的边。用两个并查集,第一个并查集next1是原图所有边,第二个是每个query的边。保证处理query边的时候原图的权值小的边已经处理过了,如图1,这样一旦有回路说明可以用小的边来替换当前query的边,就不存在了,不然就是存在的!
第二点,注意并查集的next数组的更新。
再传一个别人写的
题目大意: 给出一个n个顶点, m条边的联通无向图, 每条边有权值 wi ,有q组询问, 每次询问原图中的 ki 条边, 求是否存在一种最小生成树包含这 ki 条边。 (n,m,wi,q,∑ki≤5∗105) 。
思路: 考虑离线求解。 先将所有边按从小到大排序, 每次同时考虑一堆权值均为x的边, 根据kruskal算法, 所有 < x的边已经进行了并查集缩点, 再单独考虑所有涉及了这一次权值为x的询问
qi
, 把
qi
涉及到的边单独拿出来做并查集合并, 若出现了环则
qi
这条询问判断为不存在, 再把这次的修改还原, 考虑完所有的涉及到的询问后, 把该层权值为x的边端点并查集合并后, 继续考虑下一层权值的边。
最后
以上就是欣喜夕阳为你收集整理的Codeforces 892/E Envy 最小生成树的query的全部内容,希望文章能够帮你解决Codeforces 892/E Envy 最小生成树的query所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复