基环树的最大独立集
正解就是从环上找相邻两点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;
}