HDU5923-Prediction-有继承味道的并查集

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

题意:传送门

 原题目描述在最下面。
 有一个n个节点m条边的无向图和一个m个节点的有根树(根为1)。树上每个节点和图中的某些边一一对应。
 每次询问给一个树的点的集合S,真实完整的点集合不仅包含集合里面的点,还包含这些点在树上的祖先。这个完整的点集合对应了图中一些边集合。输出这个图的边集合的联通块的个数。


思路:

  • 判断联通用并查集很方便咯。

  • 因为询问带有一点继承的味道。因为每个点的父节点也算在其中了。

  • 所以针对此题要用一个可继承的并查集:对树上每个节点维护一个图连通性的并查集。然后每个子节点\(v\)继承其父节点\(u\)的并查集,并在此基础上将新的一条边\(u->v\)添加进\(v\)节点的并查集。加边就是并查集的合并操作。

  • 对于每个询问,就把点集中每个点的并查集合并。意思就是把每个点的联通块合并在一起。最后数联通块的个数。

  • 代码中还有一点注释。

AC代码:

#include <bits/stdc++.h>
#define mme(a,b) memset((a),(b),sizeof((a)))  
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
int n, m, q;
vector<int> son[10005];
int mp[10005][2], fa[10005][505], vis[505];
int Fi(int id,int x){
  return fa[id][x]==x?x:fa[id][x]=Fi(id,fa[id][x]);
}
void un(int id,int a,int b){
  int pa=Fi(id,a),pb=Fi(id,b);
  if(pa==pb)return;
  fa[id][pb]=pa;
}
void dfs(int u,int Fa){//每个节点继承其父节点的并查集
  for(int i=1;i<=n;++i)fa[u][i]=fa[Fa][i];
  un(u,mp[u][0],mp[u][1]);
  int len=son[u].size();
  for(int i=0;i<len;++i){
    dfs(son[u][i],u);
  }
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("E://ADpan//in.in", "r", stdin);
    //freopen("E://ADpan//out.out", "w", stdout);
#endif
  int tim,tc = 0;
  scanf("%d", &tim);
  while(tim--){
    scanf("%d%d",&n,&m);
    for(int i=0;i<=m;++i)son[i].clear();
    for(int i=2,x;i<=m;++i){
      scanf("%d",&x);
      son[x].push_back(i);
    }
    for(int i=1,u,v;i<=m;++i){
      scanf("%d%d",&u,&v);
      mp[i][0]=u;mp[i][1]=v;
    }
    for(int i=0;i<=n;++i)fa[0][i]=i;
    dfs(1,0);
    printf("Case #%d:\n", ++tc);
    scanf("%d",&q);
    while(q--){
      int cnt;scanf("%d",&cnt);
      for(int i=1;i<=n;++i)fa[0][i]=i,vis[i]=0;
      //将cnt个节点及其父节点的并查集合并
      for(int i=0,x;i<cnt;++i){
        scanf("%d",&x);
        for(int j=1;j<=n;++j){
          int tfa = Fi(x,j);
          //这个处理是精髓
          if(tfa!=j){//表示在此子图中这两个点联通,故合并
            un(0,tfa,j);
          }
        }
      }
      int ans=0;
      for(int i=1;i<=n;++i){
        int tmp = Fi(0,i);
        if(vis[tmp]==0){
          vis[tmp]=1;
          ans++;
        }
      }
      printf("%d\n", ans);
    }
  }
  return 0;
}

原题目描述:

Problem Description
There is a graph G=⟨VG,EG⟩ with |VG|=n and |EG|=m, and a magic tree T=⟨VT,ET⟩) rooted at 1, which contains m vertices.

Each vertex of the magic tree corresponds to an edge in the original graph G and each edge occurs in the magic tree exactly once.

Each query includes a set S(S⊆VT), and you should tell Mr. Frog the number of components in the modified graph G‘=(VG,E‘G), where E‘G is a set of edges in which every edge corresponds to a vertex v in magic tree T satisfying at least one of the following two conditions:

∙v∈S.
∙v is an ancestor of some vertices in S.

Note that the queries are independent, and namely one query will not influence another.

Input
The input contains several test cases and the first line of the input data is an integer T, denoting the number of test cases.

For each test case, the first line contains two integers n and m(1≤n≤500,1≤m≤10000), where n is the number of vertices and m is the number of edges.

The second line contains m - 1 integers describing the magic tree, i-th integer represents the parent of the (i + 1)-th vertex.

Then the following m lines describe the edges of the graph G. Each line contains two integers u and v indicating the two ends of the edge.

The next line contains only one integer q(1≤q≤50000), indicating the number of queries.

Then the following q lines represent queries, i-th line represents the i-th query, which contains an integer ki followed by ki integers representing the set Si.

It is guarenteed that ∑qi=1ki≤300000.

Output
For each case, print a line "Case #x:", where x is the case number (starting from 1).

For each query, output a single line containing only one integer representing the answer, namely the number of components.

Sample Input

1
5 4
1 1 3
1 2
2 3
3 4
4 5
3
1 2
2 2 3
2 2 4

Sample Output

Case #1:
3
2
1
Hint

magic tree and the original graph in the sample are:

In the first query, S = {2} and the modified graph G' = {{1, 2, 3, 4}, {(1, 2), (2, 3)}}, thus the number of the components in the modified graph is 3.
In the second query, S = {1, 2, 3}, where 1 is the ancestor of 2 (and 3) in the magic tree, and the modified graph G'' = {{1, 2, 3,4}, {(1, 2), (2, 3), (3, 4)}},
therefore the number of the components in the modified graph is 2.
In the third query, S = {1, 2, 3, 4}, where 1 is the ancestor of 2 (and 4), 3 is the ancestor of 4, and the modified graph G' = {{1, 2, 3,4}, {(1, 2), (2, 3), (3,4), (4, 5)}},
therefore the answer equals to 1.

Source
2016CCPC东北地区大学生程序设计竞赛 - 重现赛

posted @ 2018-08-06 22:29  Cwolf9  阅读(268)  评论(0编辑  收藏  举报