这题真的是无语了,在哪个岛上根本就没有任何的用处……不过我是画了下图,感受到一定是仙人掌,并不会证。有谁会证的求解……
如果当做仙人掌来做确实十分的简单。只要像没有上司的舞会一样树形dp就好了,遇到环出现的时候把环遍历一遍单独求解,和小C的独立集完全是一样的做法。
#include <bits/stdc++.h> using namespace std; #define maxn 500000 #define int long long #define INF 999999999 int n, m, cnp = 1; int f[maxn][2], fa[maxn], val[maxn]; int ans, timer, dfn[maxn], low[maxn];struct edge {int cnp = 1, head[maxn], to[maxn], last[maxn];void add(int u, int v){to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;} }E1;int read() {int x = 0, k = 1;char c;c = getchar();while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x * k; }void Solve(int u, int v) {bool flag = 0;if(u == 3) flag = 1;int f1 = 0, f0 = 0;for(int i = v; i != u; i = fa[i]){int t0 = f0 + f[i][0], t1 = f1 + f[i][1];f0 = max(t0, t1), f1 = t0;}f[u][0] += f0;f1 = -INF, f0 = 0;for(int i = v; i != u; i = fa[i]){int t0 = f[i][0] + f0, t1 = f[i][1] + f1;f1 = t0, f0 = max(t0, t1);}f[u][1] += f1; }void Tarjan(int u) {dfn[u] = low[u] = ++ timer;f[u][0] = 0, f[u][1] = val[u];for(int i = E1.head[u]; i; i = E1.last[i]){int v = E1.to[i];if(v == fa[u]) continue;if(!dfn[v]) {fa[v] = u; Tarjan(v);low[u] = min(low[u], low[v]);}else low[u] = min(low[u], dfn[v]);if(low[v] > dfn[u] && fa[v] == u) f[u][1] += f[v][0], f[u][0] += max(f[v][0], f[v][1]);}for(int i = E1.head[u]; i; i = E1.last[i]){int v = E1.to[i];if(dfn[v] > dfn[u] && fa[v] != u) Solve(u, v);} }signed main() {n = read(), m = read();for(int i = 1; i <= m; i ++){int u = read(), v = read();E1.add(u, v);}for(int i = 1; i <= n; i ++)val[i] = read();for(int i = 1; i <= n; i ++){if(dfn[i]) continue; Tarjan(i); ans += max(f[i][1], f[i][0]);}printf("%lld\n", ans);return 0; }