P1453 城市环路

【题意】

基环树上的最大点权独立集

【分析】

我们采用删去环上的一条边的方式来计算

因为一棵树上的最大点权独立集我们很熟练,所以问题就是删去的那条边的贡献

P1453 城市环路

图源 https://www.luogu.com.cn/blog/ShadderLeave/ji-huan-shu-bi-ji

 

考虑删去的边连接了lt和rt

我们只需要考虑强制规定lt和rt不能同时选

这样我们分别从lt和rt计算两次取max即可

 

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,head[maxn],tot,fa[maxn];
struct edge
{
    int to,nxt;
}e[maxn<<1];
void add(int x,int y)
{
    e[++tot].to=y; e[tot].nxt=head[x]; head[x]=tot;
}
int p[maxn];
int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
int f[maxn][2];
void dfs(int u,int fa)
{
    f[u][1]=p[u];
    for(int i=head[u];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if(to==fa) continue;
        dfs(to,u);
        f[u][0]+=max(f[to][1],f[to][0]);
        f[u][1]+=f[to][0];
    }
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&p[i]),fa[i]=i;
    int x,y,lt,rt;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        x++; y++;
        int fx=find(x),fy=find(y);
        if(fx==fy) {lt=x,rt=y; continue;}
        add(x,y); add(y,x); fa[fx]=fy;
    }
    int ans=0;
    dfs(rt,0); ans=max(ans,f[rt][0]);
    memset(f,0,sizeof(f));
    dfs(lt,0); ans=max(ans,f[lt][0]);
    double k;
    scanf("%lf",&k);
    printf("%.1f",ans*k);
    return 0;
}

 

上一篇:Unity - 研究tolua(2) - C# 调用 lua


下一篇:MySQL的MyISAM和InnoDB