P1453 城市环路

基环树的最大独立集

正解就是从环上找相邻两点s,t,求出分别以s和t为根,求max(dp[s][0],dp[t][0])

这就是答案。因为s和t不能同时选,那只要有一个不选就行。

我的解法是单独求基环树上的点。。。。。很捞

我的写法

#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;

const int maxn = 2e5 + 11;
vector<int>G[maxn];
void insert(int be, int en) {
	G[be].push_back(en);
}
stack<int>s;
vector<int>ins;

ll list[maxn];
int vis[maxn];
int dfs1(int x, int fa) {
	if (vis[x]) {
		if (ins.size() != 0) return 0;
		while (s.size()) {
			int a = s.top();
			s.pop();
			ins.push_back(a);
			if (a == x) break;
		}
		return 0;
	}
	vis[x] = 1;
	s.push(x);
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		dfs1(p, x);
	}
	if (s.size()) s.pop();
	return 0;
}
ll dp[maxn][3];

int dfs(int x, int fa) {
	dp[x][1] = list[x];
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa || vis[p]) continue;
		dfs(p, x);
		dp[x][1] += dp[p][0];
		dp[x][0] += max(dp[p][0], dp[p][1]);
	}
	return 0;
}
ll chal[maxn][3];


int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &list[i]);
	}
	for (int i = 0; i < n; i++) {
		int be, en;
		scanf("%d %d", &be, &en);
		be++, en++;
		insert(be, en);
		insert(en, be);
	}
	double k;
	scanf("%lf", &k);

	dfs1(1, -1);

	for (int i = 1; i <= n; i++) vis[i] = 0;
	for (int i = 0; i < ins.size(); i++) vis[ins[i]] = 1;

	for (int i = 0; i < ins.size(); i++) {
		int root = ins[i];
		dfs(root, -1);
	}
	ll ans = 0;
	//开头必选
	chal[ins[0]][1] = dp[ins[0]][1];
	chal[ins[0]][0] = 0;
	int len = ins.size();

	for (int i = 1; i < ins.size(); i++) {
		int x = ins[i];
		int p = ins[i - 1];
		chal[x][0] = dp[x][0];
		chal[x][1] = dp[x][1];

		chal[x][0] += max(chal[p][1], chal[p][0]);
		chal[x][1] += chal[p][0];
	}
	ans = max(chal[ins[len - 1]][0], ans);//开头选,结尾不能选

	//开头不选
	chal[ins[0]][1] = 0;
	chal[ins[0]][0] = dp[ins[0]][0];

	for (int i = 1; i < ins.size(); i++) {
		int x = ins[i];
		int p = ins[i - 1];

		chal[x][0] = dp[x][0];
		chal[x][1] = dp[x][1];

		chal[x][0] += max(chal[p][1], chal[p][0]);
		chal[x][1] += chal[p][0];
	}
	int root = ins[len - 1];

	ans = max(ans, chal[root][0]);
	ans = max(ans, chal[root][1]);
	double a = 1.0*ans * k;
	printf("%.1lf
", a);
	return 0;
}

  

题解的写法

#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;

const int maxn = 2e5 + 11;
vector<int>G[maxn];
void insert(int be, int en) {
	G[be].push_back(en);
}

vector<int>ins;

ll list[maxn];
int vis[maxn];
int ss, tt;

int dfs1(int x,int fa) {
	if (vis[x]) {
		if (ss == 0 && tt == 0) {
			ss = x;
			tt = fa;
		}
		return 0;
	}
	vis[x] = 1;
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		dfs1(p, x);
	}
	return 0;
}

ll dp[maxn][3];

int dfs(int x, int fa) {
	dp[x][1] = list[x];
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		if (x == ss && p == tt) continue;
		if (x == tt && p == ss) continue;

		dfs(p, x);
		dp[x][1] += dp[p][0];
		dp[x][0] += max(dp[p][0], dp[p][1]);
	}
	return 0;
}
ll chal[maxn][3];


int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &list[i]);
	}
	for (int i = 0; i < n; i++) {
		int be, en;
		scanf("%d %d", &be, &en);
		be++, en++;
		insert(be, en);
		insert(en, be);
	}

	double k;
	scanf("%lf", &k);
	dfs1(1, -1);
	ll ans = 0;

	dfs(ss, -1);
	ans = max(dp[ss][0], ans);
	
	for (int i = 1; i <= n; i++) dp[i][0] = dp[i][1] = 0;

	dfs(tt, -1);
	ans = max(dp[tt][0], ans);

	double a = 1.0*ans*k;
	printf("%.1lf
", a);
	return 0;
}

  

原文地址:https://www.cnblogs.com/lesning/p/14082943.html