codeforces 891C

来源:互联网 发布:贷款软件 编辑:程序博客网 时间:2024/05/22 17:57

给出一个无向图,每次询问图中的一个边集,是否存在包含这个边集的MST

考虑怎么判断是否存在包含某一条边的MST
若他不在原图的MST上,显然只能尝试用它替换一条权值相等的,MST上的边
设他的权值为c,可以先对权< c的边先做kruskal建出生成树,用这些边将原图缩点
然后若这条边在这个缩完点的图上不是自环,就合法

对于每个询问的边集,不同的边权显然互相独立
这个边集合法的充要条件是每条边合法且相同边权的边在它的那个图上不成环

将这些询问离线掉,按边权从小到大建出图,每一步后缩点,然后对于每个询问若他有当前权的边就判这些边是否成环
判环好像有一些高级的随机分配值用异或判的姿势但我不会
我们可以直接暴力的用并查集判环
但每个询问判完后要撤销操作所以写按秩合并的并查集,带个log

nlogn

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;inline void read(int &x){    char c; while(!((c=getchar())>='0'&&c<='9'));    x=c-'0';    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';}const int maxn = 510000;const int maxm = 510000;const int maxq = 510000;int n,m,q;struct edge{int i,x,y,c;}e[maxm]; int To[maxm];inline bool cmp(const edge x,const edge y){return x.c<y.c;}struct node{int i,j,x;};inline bool operator <(const node x,const node y){return x.x>y.x;}priority_queue<node>Q;vector<int>V[maxq];int ans[maxq];int fa[maxn],siz[maxn];int t[maxn][2],tp;int findfa(const int x){return fa[x]==x?x:findfa(fa[x]);}bool merge(int ei){    int x=e[ei].x,y=e[ei].y;    int f1=findfa(x),f2=findfa(y);    if(f1==f2) return false;    if(siz[f1]<siz[f2]) swap(f1,f2);    fa[f2]=f1,siz[f1]+=siz[f2];    t[++tp][0]=f1,t[tp][1]=f2;    return true;}void gback(){    while(tp)    {        int x=t[tp][0],y=t[tp--][1];        fa[y]=y; siz[x]-=siz[y];    }}int main(){    read(n); read(m);    for(int i=1;i<=m;i++) read(e[i].x),read(e[i].y),read(e[i].c),e[i].i=i;    sort(e+1,e+m+1,cmp);    for(int i=1;i<=m;i++) To[e[i].i]=i;    read(q);    for(int i=1;i<=q;i++)    {        ans[i]=0; int kk; read(kk);        while(kk--)         {            int cc; read(cc); cc=To[cc];            V[i].push_back(cc);        }kk=V[i].size();        sort(V[i].begin(),V[i].end());        Q.push((node){i,0,V[i][0]});    }    for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1;    for(int i=1;i<=m;)    {        int j=i+1;for(;j<=m&&e[j].c==e[i].c;j++);j--;        while(!Q.empty())        {            node now=Q.top(); if(now.x>j) break;            Q.pop();            for(;now.j<V[now.i].size()&&V[now.i][now.j]<=j;now.j++)                if(!merge(V[now.i][now.j])) break;            gback();            if(now.j==V[now.i].size()) { ans[now.i]=1; continue; }            now.x=V[now.i][now.j];            if(now.x>j) Q.push(now);        }        for(;i<=j;i++) merge(i);        tp=0;    }    for(int i=1;i<=q;i++) puts(ans[i]==1?"YES":"NO");    return 0;}
原创粉丝点击