zoukankan      html  css  js  c++  java
  • [Codeforces 911F] Tree Destruction 解题报告(贪心)

    题目链接:

    http://codeforces.com/contest/911/problem/F

    题目大意:

    给你一棵树,每次挑选这棵树的两个度数为1的点,加上他们之间的边数(距离),然后将其中一个点去掉,问你边数(距离)之和最大可以是多少.

    要求输出每次选择的两个点和删掉的点

    题解:

    贪心题,策略是每次选择一个度数为1的点和距离它较远的直径的端点(显然直径的端点度数为1),然后把这个点删掉保留直径的端点。直到只剩下直径的时候才开始删掉直径上的点

    为什么?考虑到先删一个直径外的点再删直径的端点一定不会比删掉一个直径的端点再删这个点更劣(不妨画个图?)。

    应该还有这么个结论吧,距离任意一个点最远的叶子节点一定是直径的一个端点,感觉挺正确的

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int N=2e5+15;
    int n;
    int d1[N],d2[N],deg[N],vis[N],a[N],b[N],c[N];
    vector <int> g[N];
    inline int read()
    {
        char ch=getchar();
        int s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    void dfs(int x,int fa,int *d)
    {
        for (int i=0;i<g[x].size();i++)
        {
            int y=g[x][i];
            if (y==fa) continue;
            d[y]=d[x]+1;
            dfs(y,x,d);
        }
    }
    void out(int x,int fa,int goal)
    {
        for (int i=0;i<g[x].size();i++)
        {
            int y=g[x][i];
            if (vis[y]||y==fa) continue;
            printf("%d %d %d
    ",x,goal,x);
            out(y,x,goal);
        }
    }
    int main()
    {
        n=read();
        for (int i=1,u,v;i<n;i++)
        {
            u=read();v=read();
            g[u].push_back(v);g[v].push_back(u);
            deg[u]++;deg[v]++;
        }
        int p1,p2,mx=0;
        d1[1]=0;dfs(1,-1,d1);
        for (int i=1;i<=n;i++) if (d1[i]>mx) {mx=d1[i];p1=i;}
        d1[p1]=0;dfs(p1,-1,d1);
        mx=0;for (int i=1;i<=n;i++) if (d1[i]>mx) {mx=d1[i];p2=i;}
        d2[p2]=0;dfs(p2,-1,d2);
        queue<int> q;
        ll ans=0;
        int tot=0;
        for (int i=1;i<=n;i++) if (d1[i]+d2[i]!=d1[p2]&&deg[i]==1) q.push(i);
        while (!q.empty())
        {
            int k=q.front();q.pop();
            ans+=max(d1[k],d2[k]);
            a[++tot]=k;b[tot]=(d1[k]>d2[k])?p1:p2;c[tot]=k;vis[k]=1;
            for (int i=0;i<g[k].size();i++)
            {
                int y=g[k][i];
                if (vis[y]) continue;
                --deg[y];
                if (d1[y]+d2[y]!=d1[p2]&&deg[y]==1) q.push(y);
            }
        }
        ans+=1ll*(d1[p2]+1)*d1[p2]/2;
        printf("%lld
    ",ans);
        for (int i=1;i<=tot;i++) printf("%d %d %d
    ",a[i],b[i],c[i]);
        out(p1,-1,p2);
        return 0;
    }
  • 相关阅读:
    zoj2132-The Most Frequent Number
    ant-design getFieldDecorator 无法获取自定义组件的值
    ant-design-pro Login 组件 实现 rules 验证
    js 终止 forEach 循环
    js 终止 for 循环
    vue打包后出现一些map文件的解决方法
    ant font 本地化
    react 设置代理(proxy) 实现跨域请求
    ES6 async 与 await 实战
    {...formItemLayout} 标签布局
  • 原文地址:https://www.cnblogs.com/xxzh/p/9764423.html
Copyright © 2011-2022 走看看