codeforce 891 C
对每个k值判是否成环。
正确性基于拟阵的性质(那个k开头的算法的正确性)。
#include <bits/stdc++.h> #define N 500005 using namespace std; int par[N],rk[N]; int root(int x){while(x^par[x]) x=par[x];return x;} struct his{int u, rk1;int v, rk2;}; void unite(int x, int y){ if(rk[x] > rk[y])par[y] = x; else{par[x] = y;if(rk[x] == rk[y])++rk[y];} } void divide(const his &x){ par[x.u] = x.u;par[x.v] = x.v; rk[x.u] = x.rk1;rk[x.v] = x.rk2; } struct edge{ int u, v, l; }e[N]; int b[N]; his h[N]; struct qedge{ int eid, qid; }a[N]; bool cmp(int x, int y){return e[x].l < e[y].l;} bool cmp2(const qedge &x, const qedge &y){return e[x.eid].l < e[y.eid].l || (e[x.eid].l == e[y.eid].l && x.qid < y.qid); } bool ans[N]; int n,m,u,v,l; int main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++){ scanf("%d%d%d", &u, &v, &l); e[i] = {u, v, l}; b[i] = i; } int q; scanf("%d", &q); int nqe = 0,k; for(int i = 0; i < q; i++){ scanf("%d", &k); for(int j = 0; j < k; j++){ int x; scanf("%d", &x); a[nqe++] = {x, i}; } } sort(a, a + nqe, cmp2); for(int i = 1; i <= n; i++) par[i] = i; sort(b + 1, b + m + 1, cmp); for(int i = 1, j = 0; i <= m && j < nqe; ){ for(; e[b[i]].l < e[a[j].eid].l; i++){ int r1 = root(e[b[i]].u); int r2 = root(e[b[i]].v); if(r1 != r2) unite(r1, r2); } for(; j < nqe && e[a[j].eid].l == e[b[i]].l; ){ int sz = 0; for(int k = a[j].qid; a[j].qid == k && e[a[j].eid].l == e[b[i]].l; j++){ if(ans[k]) continue; auto &x = e[a[j].eid]; int r1 = root(x.u), r2 = root(x.v); if(r1 == r2) ans[k] = 1; else{ h[sz++] = {r1, rk[r1], r2, rk[r2]}; unite(r1, r2); } } for(int i=sz-1;~i;i--) divide(h[i]); } } for(int i = 0; i < q; i++) puts(ans[i] ? "NO" : "YES"); return 0; }