洛谷 P1453 城市环路
个点条边,题目保证连通,所以原图是个无向的基环树,考虑基环树。
这题可以用树形 + 环形实现。
首先把环给找出来,然后对于环上的每个点,做以为根节点的树形(类似没有上司的舞会)。
然后做环形,需要注意两点:
1、转移的顺序是序
2、因为是环,起点和终点的状态不能冲突,所以需要枚举起点的状态,求两遍环形取最大值
#include<bits/stdc++.h> using namespace std; #define fr first #define se second #define et0 exit(0); #define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++) #define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; typedef unsigned long long ULL; const int INF = 0X3f3f3f3f, N = 1e5 + 10, MOD = 1e9 + 7; const double eps = 1e-7, pi = acos(-1); int n; double k; int p[N]; int head[N], idx; struct EGDE { int to, next; } eg[N << 1]; void add(int x, int y) { eg[idx].to = y; eg[idx].next = head[x]; head[x] = idx++; } int d[N], st[N]; // u不在环上: st[u] == true void find_c() { queue<int> q; rep(i, 0, n - 1) if (d[i] == 1) q.push(i); while (!q.empty()) { int u = q.front(); q.pop(); st[u] = true; for (int i = head[u]; ~i; i = eg[i].next) { int to = eg[i].to; if (st[to]) continue; if (--d[to] == 1) q.push(to); } } } int f[N][2]; void DP_1(int u, int fa) { f[u][1] = p[u]; for (int i = head[u]; ~i; i = eg[i].next) { int to = eg[i].to; if (to == fa || st[to] == false) continue; DP_1(to, u); f[u][0] += max(f[to][1], f[to][0]); f[u][1] += f[to][0]; } } int Start, cnt, dfs_id[N]; void dfs(int u, int fa) { dfs_id[++cnt] = u; for (int i = head[u]; ~i; i = eg[i].next) { int to = eg[i].to; if (to == fa || st[to] || to == Start) continue; dfs(to, u); break; } } int dp[N][2], ans; void DP_2() { memset(dp, 0xcf, sizeof dp); dp[1][1] = f[dfs_id[1]][1]; rep(i, 2, cnt) { dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]) + f[dfs_id[i]][0]; dp[i][1] = dp[i - 1][0] + f[dfs_id[i]][1]; } ans = dp[cnt][0]; memset(dp, 0xcf, sizeof dp); dp[1][0] = f[dfs_id[1]][0]; rep(i, 2, cnt) { dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]) + f[dfs_id[i]][0]; dp[i][1] = dp[i - 1][0] + f[dfs_id[i]][1]; } ans = max(ans, max(dp[cnt][0], dp[cnt][1])); } void work() { memset(head, -1, sizeof head); scanf("%d", &n); rep(i, 0, n - 1) scanf("%d", p + i); rep(i, 0, n - 1) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); d[x]++, d[y]++; } scanf("%lf", &k); //找环 find_c(); Start = -1; rep(i, 0, n - 1) { if (!st[i]) { DP_1(i, -1); if (Start == -1) Start = i; } } dfs(Start, -1); DP_2(); printf("%.1lf\n", ans * k); } signed main() { int test = 1; // cin >> test; while (test--) { work(); } return 0; }
本文作者:xhy666
本文链接:https://www.cnblogs.com/xhy666/p/16549063.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步