1. 程式人生 > >CodeForces - 891C: Envy(可撤銷的並查集&最小生成樹)

CodeForces - 891C: Envy(可撤銷的並查集&最小生成樹)

note query ble rap 一個 width more imu single

For a connected undirected weighted graph G, MST (minimum spanning tree) is a subgraph of G 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 graph G

, 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 the i-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 integer ki (1 ≤ ki ≤ n - 1) — the size of edges subset and continues with ki distinct space-separated integers from 1 to m — the indices of the edges. It is guaranteed that the sum of ki for 1 ≤ 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 7
1 2 2
1 3 2
2 3 1
2 4 1
3 4 1
3 5 2
4 5 2
4
2 3 4
3 3 4 5
2 1 7
2 1 2
Output
YES
NO
YES
NO

Note

This is the graph of sample:

技術分享圖片

Weight of minimum spanning tree on this graph is 6.

MST with edges (1, 3, 4, 6), contains all of edges from the first query, so answer on the first query is "YES".

Edges from the second query form a cycle of length 3, so there is no spanning tree including these three edges. Thus, answer is "NO".

題意:給定N點M點的無向圖,M>=N-1,然後給出Q個詢問,每個詢問給出一個邊集,回答這個邊集是否存在於一個最小生成樹裏。

思路:如果是問一條邊,那麽我們可以得到最小生成樹,然後如果其是樹邊,或者不超過形成的環的最大邊,久說明可以。

但是這裏不算問一條邊,而是邊集,我們如果按照同樣的方法,取驗證這些邊是否ok,則會出錯,因為邊集內部也可能出現環。

我們已經最小生成樹的最重要的結論:

我們按權值給邊分類,同一類的邊貢獻的邊的數量是一定的,而且任選其中一種方案,其連通性是相同的。

假設現在只有一個詢問,詢問的邊集按邊權排序,權值相同的一塊處理,處理到邊權為X的時候,[0,X)的部分已經構造號了,如果把詢問裏邊權為X的加進去會產生環,則說明次詢問為“NO”。處理完X,把詢問中X部分的並查集撤銷,然後把原圖X連通。

用個時間軸即可用當前的並查集。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define F first
#define S second
using namespace std;
const int maxn=500010;
vector<int>e[maxn];
vector<pii>G[maxn];
int u[maxn],v[maxn],w[maxn],,ans[maxn];
int fa[maxn],t[maxn],tf[maxn],times;
int find(int x){
    if(x!=fa[x]) fa[x]=find(fa[x]);
    return fa[x];
}
int find2(int x){ //時間軸,可撤銷。 
    if(t[x]!=times) tf[x]=fa[x],t[x]=times;
    if(x!=tf[x]) tf[x]=find2(tf[x]);
    return tf[x];
}
int main()
{
    int N,M,Q,Mx=0;
    scanf("%d%d",&N,&M);
    rep(i,1,N) fa[i]=i;
    rep(i,1,M){
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
        Mx=max(Mx,w[i]);
        e[w[i]].pb(i);
    }
    scanf("%d",&Q);
    rep(i,1,Q){
        int num; scanf("%d",&num);
        rep(j,1,num){
            int x; scanf("%d",&x);
            G[w[x]].pb(mp(i,x));
        }
    }
    rep(i,1,Mx){
        sort(G[i].begin(),G[i].end());
        int L=G[i].size(),Laxt=0;
        rep(j,0,L-1){ //處理問題 
            int id=G[i][j].F,ed=G[i][j].S;
            a=u[ed],b=v[ed];
            if(id!=Laxt) times++,Laxt=id;    
            a=find2(a); b=find2(b);
            if(a!=b) tf[a]=b;
            else ans[id]=-1;
        }
        L=e[i].size();
        rep(j,0,L-1){ //連通 
            int ed=e[i][j],a=u[ed],b=v[ed];
            a=find(a); b=find(b);
            if(a!=b) fa[a]=b;
        }
    }
    rep(i,1,Q) if(ans[i]==-1) puts("NO"); else puts("YES");
    return 0;
}

CodeForces - 891C: Envy(可撤銷的並查集&最小生成樹)