RT,比较暴力的用了tarjan的板子判环然后跑了一遍dp,部分变量及流程已经加上注释。
#include<bits/stdc++.h>
#define N 1000001
using namespace std;
using ll=long long;
struct edge{
int to,next;
};
vector<edge> E;
int head[N];
void insert(int u,int v){
E.push_back({v,head[u]});
head[u]=E.size()-1;
}
int dfn[N],low[N],scc[N],scc_size[N],scc_count,now;
bool in_stack[N];
stack<int> s;
void add_to_scc(){
scc[s.top()]=scc_count;
scc_size[scc_count]++;
in_stack[s.top()]=0;
s.pop();
}
void tarjan(int u,int f){
dfn[u]=low[u]=++now;
in_stack[u]=1;
s.push(u);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v==f)continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(in_stack[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
++scc_count;
while(s.top()!=u)add_to_scc();
add_to_scc();
}
}
int n,cnt,tscc;//tscc:环所在的scc编号
//p1 p2分别为取/不取环上的某点时,该点及该点的子树能得到的人流最大值
ll p[N],p1[N],p2[N],dp[N][2],ans;
double k;
//dfs计算p1和 p2
ll calc(int x,int fa,bool limit){
ll res0=0,res1=p[x];
for(int i=head[x];~i;i=E[i].next){
int v=E[i].to;
if(v==fa||scc[v]==tscc)continue;
res0+=calc(v,x,0);
if(!limit)res1+=calc(v,x,1);
}
if(limit)return res0;
return max(res0,res1);
}
int main(){
memset(head,-1,sizeof head);
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1,u,v;i<=n;i++){
cin>>u>>v;
insert(u+1,v+1);
insert(v+1,u+1);
}
cin>>k;
//----tarjan--------------------------------
tarjan(1,1);
//遍历取tscc
for(int i=1;i<=scc_count;i++){
if(scc_size[i]>1){
tscc=i;
break;
}
}
for(int i=1;i<=n;i++){
if(scc[i]==tscc){
cnt++;
p1[i]=calc(i,i,0);
p2[i]=calc(i,i,1);
}
}
//----dp-------------------------------
//1取 cnt不取
dp[1][1]=p1[1];
dp[1][0]=-1e17;
for(int i=2;i<=cnt;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1])+p2[i];
dp[i][1]=dp[i-1][0]+p1[i];
}
ans=dp[cnt][0];
//1不取
dp[1][1]=-1e17;
dp[1][0]=p2[1];
for(int i=2;i<=cnt;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1])+p2[i];
dp[i][1]=dp[i-1][0]+p1[i];
}
ans=max(ans,max(dp[cnt][0],dp[cnt][1]));
printf("%.1lf\n",static_cast<double>(ans)*k);
return 0;
}
目前看了题解区之后用更为简便的方法A了,但是自己的代码看了一下午都没找出错来,救救孩子吧QWQ