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