HDU 5923 Prediction(2016 CCPC东北地区大学生程序设计竞赛 Problem B)

题目链接  2016 CCPC东北地区大学生程序设计竞赛 B题

题意  给定一个无向图和一棵树,树上的每个结点对应无向图中的一条边,现在给出$q$个询问,

   每次选定树中的一个点集,然后真正被选上的是这些点以及这些点的所有祖先。

   只有标号在树中真正被选上的点代表的这些原图中的边是存在的,这样就构成了一个新的图。求这个图的连通块个数。

dfs整棵树,记$f[x]$为若$x$以及$x$的所有祖先被选上,那么构成的新的图的并查集)

这个实现比较简单,搜索的时候打上标记,回来的时候撤销即可。

这样预处理的时间复杂度是$O(nm)$的。

然后对于每个询问,把$k$个询问的并查集全部合并就可以了。

时间复杂度$O(nm + ∑kn)$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second

typedef long long LL;

const int N = 523;
const int M = 1e4 + 10;

int T;
int ca = 0;
int n, m, q;
int ans;
int a[M], b[M], c[N], f[M][N];
int father[N];
vector <int> g[M];

int getfather(int x){
	return father[x] == x ? x : father[x] = getfather(father[x]);
}

void dfs(int x, int fa){
	rep(i, 1, n) father[i] = f[fa][i];
	int fx = getfather(a[x]);
	int fy = getfather(b[x]);
	father[fx] = fy;
	rep(i, 1, n) father[i] = getfather(i);
	rep(i, 1, n) f[x][i] = father[i];
	for (auto u : g[x]){
		dfs(u, x);
	}
}

int main(){

	scanf("%d", &T);
	while (T--){
		printf("Case #%d:\n", ++ca);
		scanf("%d%d", &n, &m);
		rep(i, 0, m + 1) g[i].clear();

		rep(i, 2, m){
			int x;
			scanf("%d", &x);
			g[x].push_back(i);
		}

		memset(a, 0, sizeof a);
		memset(b, 0, sizeof b);
		rep(i, 1, m){
			scanf("%d%d", a + i, b + i);
		}

		rep(i, 1, n) f[0][i] = i;
		dfs(1, 0);

		scanf("%d", &q);
		while (q--){
			int y;
			scanf("%d", &y);
			rep(i, 1, n) father[i] = i;
			rep(i, 1, y){
				int x;
				scanf("%d", &x);
				memset(c, 0, sizeof c);
				rep(j, 1, n){
					int now = f[x][j];
					if (c[now]){
						int fx = getfather(c[now]);
						int fy = getfather(j);
						father[fx] = fy;
					}
					c[now] = j;
				}
			}

			ans = 0;
			memset(c, 0, sizeof c);
			rep(i, 1, n){
				int x = getfather(i);
				if (!c[x]) ++ans;
				c[x] = 1;
			}
			printf("%d\n", ans);
		}
	}

	return 0;
}

  

原文地址:https://www.cnblogs.com/cxhscst2/p/8454688.html

时间: 2024-10-09 20:00:45

HDU 5923 Prediction(2016 CCPC东北地区大学生程序设计竞赛 Problem B)的相关文章

HDU 5925 Coconuts 【离散化+BFS】 (2016CCPC东北地区大学生程序设计竞赛)

Coconuts Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 524    Accepted Submission(s): 151 Problem Description TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams abou

HDU 5924 Mr. Frog’s Problem 【模拟】 (2016CCPC东北地区大学生程序设计竞赛)

Mr. Frog's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 312    Accepted Submission(s): 219 Problem Description One day, you, a clever boy, feel bored in your math class, and then fall

HDU 5927 Auxiliary Set 【DFS+树】(2016CCPC东北地区大学生程序设计竞赛)

Auxiliary Set Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 873    Accepted Submission(s): 271 Problem Description Given a rooted tree with n vertices, some of the vertices are important. An a

HDU 5922 Minimum’s Revenge 【模拟】 (2016CCPC东北地区大学生程序设计竞赛)

Minimum's Revenge Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 283    Accepted Submission(s): 219 Problem Description There is a graph of n vertices which are indexed from 1 to n. For any pai

2016CCPC东北地区大学生程序设计竞赛 - 重现赛 1008(hdu 5929)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5929 Problem Description Mr. Frog learned a basic data structure recently, which is called stack.There are some basic operations of stack: ? PUSH x: put x on the top of the stack, x must be 0 or 1.? POP

2016CCPC东北地区大学生程序设计竞赛1008/HDU 5929 模拟

Basic Data Structure Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 78    Accepted Submission(s): 12 Problem Description Mr. Frog learned a basic data structure recently, which is called stack.

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

链接http://acm.hdu.edu.cn/showproblem.php?pid=5924 题意:根据公式求C,D 解法:打表找规律 #include <bits/stdc++.h> using namespace std; #define ll long long int main() { int t,cnt=1; scanf("%d",&t); while(t--) { ll a,b; scanf("%I64d%I64d",&a

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

链接http://acm.hdu.edu.cn/showproblem.php?pid=5926 题意:给我们一个矩阵,问你根据连连看的玩法可以消去其中的元素 解法:连连看怎么玩,就怎么写,别忘记边界 #include<stdio.h> //#include<bits/stdc++.h> #include<string.h> #include<iostream> #include<math.h> #include<sstream> #

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

链接http://acm.hdu.edu.cn/showproblem.php?pid=5922 题意:最小生成树,但边的权值是连接两点的最小公倍数 解法:不要真的写最小生成树啦,只要其他点和第一点相连,边的权值就是最小的,相加就好了 #include <bits/stdc++.h> using namespace std; #define ll long long int main() { int t,cnt=1; scanf("%d",&t); while(t-