树形DP,没有上司的舞会的模型。。。
每个联通块有且只有一个环
对每个环拆一条边,这个边的两边不能同时选,对2个点都跑一遍上司的舞会
统计答案即可
/*
一个联通块
有且只有一个环
拆环
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL n;
LL a[1000006],b[1000006];
struct oppo{
LL to,nex;
}rod[2000006];
LL head[1000006],tot=1;
void add(LL from,LL to)
{
rod[++tot].to=to;
rod[tot].nex=head[from];
head[from]=tot;
}
bool dis[2000006];
bool vis[2000006];
LL dp[1000006][4];
void dps(LL x,LL fa)
{
vis[x]=1;
dp[x][1]=a[x];
dp[x][0]=0;
for(LL i=head[x];i;i=rod[i].nex){
if(dis[i]||rod[i].to==fa) continue;
dps(rod[i].to,x);
dp[x][1]+=dp[rod[i].to][0];
dp[x][0]+=max(dp[rod[i].to][1],dp[rod[i].to][0]);
}
}
LL dfs(LL x,LL fa)
{
vis[x]=1;
for(LL i=head[x];i;i=rod[i].nex)
{
if(rod[i].to==fa) continue;
if(vis[rod[i].to]){
LL k;
dis[i]=1;
dis[i^1]=1;
k=a[rod[i].to];
a[rod[i].to]=0;
dps(x,0);
a[rod[i].to]=k;
LL y=max(dp[x][0],dp[x][1]);
k=a[x];
a[x]=0;
dps(rod[i].to,0);
a[x]=k;
LL z=max(dp[rod[i].to][0],dp[rod[i].to][1]);
return max(y,z);
}
LL k=dfs(rod[i].to,x);
if(k)
return k;
}
return 0;
}
void work()
{
LL ans=0;
for(LL i=1;i<=n;i++)
{
if(!vis[i])
ans+=dfs(i,0);
}
cout<<ans<<"\n";
}
int main()
{
freopen("knight.in","r",stdin);
freopen("knight.out","w",stdout);
cin>>n;
for(LL i=1;i<=n;i++){
scanf("%lld%lld",&a[i],&b[i]);
add(b[i],i);
add(i,b[i]);
}
work();
return 0;
}
这题用
vector<int>g[n]
怎么找到断开的边?如果用vector存图,这边建议您随便标记乱YY呢,亲
什么是乱yy?
我百度回来了,有胡思乱想的意思
用vector怎么断边?
先找到环,在环上随便断一个边
vector注意断反向边,标记一下即可