附加数据全部T完
查看原帖
附加数据全部T完
776232
zhizhizhiwang楼主2024/7/15 16:05

code:

/*
城市环路
树形dp + 环形dp
[没有上司的舞会]

基环树 -> 有一个环的树

一条边上两个点只能选一个 (父子互斥)

1. 找环 -> 不断去掉入度为1的叶子节点,最终只剩下环
	拓扑排序
2.没有上司的舞会



*/


#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

int const N = 1e5 + 10;

double ans1 = 0, ans2 = 0;
vector<int> tree[N];
vector<int> circle;
int w[N];
long long f[N][2]; //选/不选 -> 0/1 
int n;
double k;//?

void dp(int u, int fa)
{
	f[u][1] = w[u];
	f[u][0] = 0;
	
	for(int x : tree[u])
	{
		if(x != fa) 
		{
			dp(x, u);
			f[u][0] += max(f[x][0], f[x][1]);
			f[u][1] += f[x][0];
		}
	}
}

int main()
{
	scanf("%d",&n);
	for(int i = 0;i < n;i++) scanf("%d", &w[i]);
	for(int u, v, i = 0;i < n;i++) 
	{
		scanf("%d %d", &u, &v);
		tree[u].push_back(v);
		tree[v].push_back(u);	
	}
	scanf("%lf", &k);
	
	
	for(int i = 0; i < n; i++)
		circle.push_back(i);
	
	vector<int> out;
	do
	{
		out.clear();
		for(int i : circle)
		{
			if (tree[i].size() == 1)
			{
				out.push_back(i);
				circle.erase(circle.begin() + i);
			}
		}
	}while(out.size() != 0);
	
	//找环
	int root1 = circle[0], root2 = circle[1];
	remove(tree[root1].begin(), tree[root1].end(), root2);
	tree[root1].pop_back();
	remove(tree[root2].begin(), tree[root2].end(), root1);
	tree[root2].pop_back();
	// 断边,转化为树
	
	dp(root1, 0);
	ans1 = f[root1][0];
	dp(root2, 0);
	ans2 = f[root2][0];
	
	printf("%.1lf", max(ans1, ans2) * k);
	return 0;
	
}

求助,附加数据全部T完(

2024/7/15 16:05
加载中...