传送门
Solution
考虑最小生成树的性质,即相同边权构成的连通性相同,所以我们只需要把边权排序然后将相同的连起来判断是否冲突即可。
Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<set> #include<map> #include<iostream> using namespace std; #define ll long long #define re register #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) inline int gi() { int f=1,sum=0;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return f*sum; } const int N=500010; struct node { int u,v,w,uu,vv,id; bool operator<(const node&b)const { return w<b.w; } }e[N],a[N]; int f[N],n,m,q,c[N],id[N]; int find(int x) { if(f[x]!=x)f[x]=find(f[x]); return f[x]; } int main() { #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif n=gi();m=gi(); for(int i=1;i<=m;i++) { e[i].u=gi(),e[i].v=gi(),e[i].w=gi(); e[i].id=i; } sort(e+1,e+m+1); for(int i=1;i<=m;i++) id[e[i].id]=i; for(int i=1;i<=n;i++)f[i]=i; int last=1; for(int i=1;i<=m;i++) { if(e[i].w!=e[i-1].w) { for(int j=last;j<i;j++) { int u=find(e[j].u),v=find(e[j].v); if(u!=v)f[v]=u; } last=i; } e[i].uu=find(e[i].u); e[i].vv=find(e[i].v); } for(int j=last;j<=m;j++) { int u=find(e[j].u),v=find(e[j].v); if(u!=v)f[v]=u; } // for(int i=1;i<=m;i++) // printf("%d %d %d %d %d\n",e[i].u,e[i].v,e[i].w,e[i].uu,e[i].vv); q=gi(); while(q--) { int k=gi(),sta=0; for(int i=1;i<=k;i++) c[i]=gi(); for(int i=1;i<=k;i++) { a[++sta]=e[id[c[i]]]; f[a[sta].uu]=a[sta].uu; f[a[sta].vv]=a[sta].vv; } sort(a+1,a+sta+1);int flag=0; for(int i=1;i<=sta;i++) { int u=a[i].uu,v=a[i].vv; if(find(u)==find(v)) { flag=1;break; } // if(!q)printf("%d %d %d %d\n",u,v,find(u),find(v)); f[find(u)]=find(v); } if(flag)puts("NO"); else puts("YES"); } return 0; }