3.26 CodeForces练习

纵饮孤独 提交于 2020-03-26 23:43:35

C. News Distribution(1400)(并查集求连通块点的个数)

分析:给定n,m,n表示n个用户,m表示组数,每组有很多人。我们可以通过并查集求连通块内的点的个数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
 
using namespace std;
const int N = 500005;
int p[N];
int sz[N];
int find(int x)
{
	if (p[x] != x) p[x] = find(p[x]);
	return p[x];
}
 
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
 
	for (int i = 1; i <= n; ++i) p[i] = i, sz[i] = 1;
 
	for (int i = 1; i <= m; ++i)
	{
		int k;
		scanf("%d", &k);
		
		if (k == 0)
			continue;
		else
		{
			int last;
			scanf("%d", &last);
			if (k >= 2)
			{
				int d;
				for (int j = 2; j <= k; ++j)
				{
					scanf("%d", &d);
					int pa = find(last), pb = find(d);
					if (pa != pb)
					{
						p[pa] = pb;
						sz[pb] += sz[pa];
					}
					last = d;
				}
			}
		}
	}
 
	for (int i = 1; i <= n; ++i)
	{
		int f = find(i);
		printf("%d ", sz[f]);
	}
	
 
	//
 
	return 0;
}

A. Sum in the tree(DFS)(贪心)

分析:偶数层为-1,偶数层的s应该最大为所有子结点s的最小值,然后还要考虑叶子节点为偶数层的时候,直接赋值父节点的s。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
using LL = long long;
const int N = 200005;
const int INF = 0x3f3f3f3f;
int h[N], e[N * 2], ne[N * 2], idx;
int s[N];
bool flag;
LL ans;
void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u, int fa)
{
	if (s[u] == -1)//偶数层
	{
		LL mn = 0x3f3f3f3f;
		for (int i = h[u]; i != -1; i = ne[i])
		{
			int j = e[i];
			if (j == fa) continue;
			mn = min(mn, (long long)s[j]);
		}
		s[u] = mn;
	}
	for (int i = h[u]; i != -1; i = ne[i])
	{
		int j = e[i];
		if (j == fa) continue;
		dfs(j, u);
		if (s[j] == 0x3f3f3f3f)
			s[j] = s[u];
	}
}

void dfs_2(int u, int father)
{
	if(flag) return;
	for (int i = h[u]; i != -1; i = ne[i])
	{
		int j = e[i];
		if (j != father)
		{
			LL t = s[j] - s[u];
			if (t < 0)
			{
				flag = true;
				return;
			}
			ans += t;
			dfs_2(j, u);
		}
	}
}

int main()
{
	int n;
	scanf("%d", &n);

	memset(h, -1, sizeof h);
	int p;
	for (int i = 2; i <= n; ++i)
	{
		scanf("%d", &p);
		add(i, p), add(p, i);
	}
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d", &s[i]);
	}
	dfs(1, -1);

	dfs_2(1, -1);
	if (flag)
	{
		puts("-1");
	}
	else
	{
		printf("%lld\n", ans + s[1]);
	}

	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!