E. Envy(可撤销并查集+离线处理)

来源:互联网 发布:软件界面修改工具 编辑:程序博客网 时间:2024/04/27 17:07
E. Envy
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

For a connected undirected weighted graph G, MST (minimum spanning tree) is a subgraph ofG that contains all of G's vertices, is a tree, and sum of its edges is minimum possible.

You are given a graph G. If you run a MST algorithm on graph it would give you only one MST and it causes other edges to become jealous. You are given some queries, each query contains a set of edges of graphG, and you should determine whether there is a MST containing all these edges or not.

Input

The first line contains two integers n,m (2  ≤ n, m  ≤ 5·105,n - 1 ≤ m) — the number of vertices and edges in the graph and the number of queries.

The i-th of the next m lines contains three integers ui,vi,wi (ui ≠ vi,1 ≤ wi ≤ 5·105) — the endpoints and weight of thei-th edge. There can be more than one edges between two vertices. It's guaranteed that the given graph is connected.

The next line contains a single integer q (1 ≤ q ≤ 5·105) — the number of queries.

q lines follow, the i-th of them contains the i-th query. It starts with an integerki (1 ≤ ki ≤ n - 1) — the size of edges subset and continues withki distinct space-separated integers from1 to m — the indices of the edges. It is guaranteed that the sum ofki for1 ≤ i ≤ q does not exceed 5·105.

Output

For each query you should print "YES" (without quotes) if there's a MST containing these edges and "NO" (of course without quotes again) otherwise.

Example
Input
5 71 2 21 3 22 3 12 4 13 4 13 5 24 5 242 3 43 3 4 52 1 72 1 2
Output
YESNOYESNO思路:首先我们知道肯定去判断询问中的边是不是多余的边,多余的边的按照最小生成树的算法,我们只用考虑边权小与当前边所构成的森林,如果加入这条边成环就是多余的,这题还有一个情况,边权相同,都不是多余的边,就是不能出现在同一个mxt中这种我们就把这些同时加进去看会不会出现环,再把每次判断加进去的撤销就行了,用栈模拟下ac代码:
#include<bits/stdc++.h>#define LL long long#define INF 0x3f3f3f3f#define INFLL 0x3f3f3f3f3f3fusing namespace std;const int maxn  = 5e5+5;int fa[maxn];int sz[maxn];int n,m;struct node{    int u,v,w;}E[maxn];struct node2{    int id,e;};struct node3{    int id,s,t;};stack<pair<int,int> >S;vector<node>E2[maxn];vector<node3>Q2[maxn];vector<node2>Q[maxn];int cmp(node2 a,node2 b){    return E[a.e].w<E[b.e].w;}int ans[maxn];int Find(int x){  //  cout<<x<<endl;    return x==fa[x]?x:Find(fa[x]);}void join(int x,int y){    if(sz[x]<=sz[y]){        fa[x] = y;        sz[y]+=sz[x];        S.push(make_pair(x,y));    }    else{        fa[y] = x;        sz[x] += sz[y];        S.push(make_pair(y,x));    }}void rem(){    pair<int,int> tmp = S.top();    //cout<<tmp.first<<endl;    S.pop();    fa[tmp.first] = tmp.first;    sz[tmp.second] -= sz[tmp.first];}int check(node3 tmp){    //cout<<"fwfwf"<<endl;    int cnt = 0;    int ret = 1;  //  cout<<"gan"<<' '<<tmp.s<<' '<<tmp.t<<endl;    for(int i = tmp.s;i<=tmp.t;i++){        int u = E[Q[tmp.id][i].e].u;        int v = E[Q[tmp.id][i].e].v;        int uu = Find(u);        int vv = Find(v);        if(uu==vv){            ret= 0;        }        else{    //            cout<<"unio1:"<<u<<' '<<v<<endl;                cnt++;            join(uu,vv);        }    }   // cout<<"gaaaaaaaaaaaa"<<endl;    //cout<<tmp.s<<' '<<tmp.t<<' '<<S.size()<<endl;    for(int i = 0;i<cnt;i++){       rem();    }    //cout<<"gggggggg"<<endl;    return ret;}int main(){    while(~scanf("%d%d",&n,&m))    {        for(int i = 0;i<=maxn-1;i++){            E2[i].clear();            Q2[i].clear();        }        for(int i = 0;i<=n;i++) fa[i] = i,sz[i] = 1;        memset(ans,0,sizeof(ans));        while(!S.empty()) S.pop();        for(int i = 1;i<=m;i++){            scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);            E2[E[i].w].push_back(E[i]);        }        int q;        scanf("%d",&q);        for(int i = 1;i<=q;i++){            int c;            scanf("%d",&c);            while(c--){                int x;                scanf("%d",&x);                node2 tmp;                tmp.id = i;                tmp.e =x;                Q[i].push_back(tmp);            }            sort(Q[i].begin(),Q[i].end(),cmp);            int s = 0;            for(int j = 1;j<Q[i].size();j++){                if(E[Q[i][j].e].w!=E[Q[i][j-1].e].w){                    node3 tmp;                    tmp.id = i;                    tmp.s = s;                    tmp.t = j-1;                    s = j;                    Q2[E[Q[i][j-1].e].w].push_back(tmp);                }            }             node3 tmp;                    tmp.id = i;                    tmp.s = s;                    tmp.t = Q[i].size()-1;                    Q2[E[Q[i][Q[i].size()-1].e].w].push_back(tmp);        }        for(int i = 1;i<=500000;i++){               // cout<<"fffffffffff"<<endl;            for(int j = 0;j<Q2[i].size();j++){                if(!check(Q2[i][j])){                    ans[Q2[i][j].id] = 1;             //   cout<<"result:"<<Q[Q2[i][j].id][Q2[i][j].t].e<<' '<<i<<endl;                }            }            for(int j = 0;j<E2[i].size();j++){                int u = Find(E2[i][j].u);                int v = Find(E2[i][j].v);                if(u!=v){                   // cout<<"unio2:"<<E2[i][j].u<<' '<<E2[i][j].v<<endl;                    join(u,v);                }            }        }        for(int i = 1;i<=q;i++){            if(ans[i]){                    puts("NO");            }            else{                puts("YES");            }        }    }}