基环树上的没有上司我舞会。我们需要把环断开。可以任取环上一对点,将该边断开,就形成了一棵树。然后从这边的两个端点(设为S,T)分别进行树形DP。DP状态设置和上司我舞会一样,然后在f[0][T]和f[0][S]中取max,这样可以保证两点不会同时选到。
可以用并查集在建图过程中建图找环。
这个的实质就是在环上最后的一条边要加入的时候不让它加入
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i(j);i<=k;++i)
#define drp(i,j,k) for(int i(j);i>=k;--i)
#define repg(x) for(int i(G.head[x]);i;i=G.next[i])
#define bug cout<<"~~~~~~~~~~~~~"<<'
';
using std::cin;
using std::cout;
typedef long long lxl;
template<typename T>
inline T max( T a, T b) {
return a > b ? a : b;
}
template<typename T>
inline T min( T a, T b) {
return a < b ? a : b;
}
const int N = 1e5 + 79;
struct graph {
int head[N], tot, next[N << 1], ver[N << 1];
inline void add(int a, int b) {
ver[++tot] = b;
next[tot] = head[a];
head[a] = tot;
}
} G;
int n, p[N], S, T, ans;
namespace bingchaji {
int fa[N];
int f[2][N];
inline int find(int x) {
while(x != fa[x]) x = fa[x] = fa[fa[x]];
return x;
}
inline void DP(int x, int pre) {
f[0][x] = 0;
f[1][x] = p[x];
repg(x) {
int y(G.ver[i]);
if(y == pre)continue;
DP(y, x);
f[0][x] += max(f[1][y], f[0][y]);
f[1][x] += f[0][y];
}
}
int main() {
int x, y;
rep(i, 1, n) {
fa[i] = i;
}
rep(i, 1, n) {
cin >> x >> y;
++x;
++y;
if(find(x) == find(y)) {
S = x;
T = y;
continue;
}
fa[find(x)] = find(y);
G.add(x, y);
G.add(y, x);
}
DP(S, 0);
ans = max(ans, f[0][S]);
DP(T, 0);
ans = max(ans, f[0][T]);
double k;
cin >> k;
cout << std::fixed << std::setprecision(1) << ans*k << '
';
return 0;
}
}
int main() {
cin >> n;
rep(i, 1, n) {
cin >> p[i];
}
bingchaji::main();
return 0;
}