• Codeforces-964D Destruction of a Tree(贪心)


    题意:给你一颗节点数目为n的树,问你能否每次删除一个度为偶数的节点,同时与该节点相连的路也被删除,能否在多次删除操作后删除掉整棵树

    题解:从根开始dfs处理出每个节点到根的距离。然后贪心的删除离根最远的偶数度节点。如何证明这个结论是正确的呢?(补题目的时候是多画图然后猜的结论,因为WA了两发后以为是错误的,然后请教了别人,并且证明了这个结论的正确性)因为离根最远的偶数度节点(其子孙一定都是奇数度数的),在将其删除后它所在的那颗树一定被分成两个奇数节点数(注意是节点数!因为只有奇数树才能进行删除操作)的树,从而它的子孙也可以开始删除操作,所以从该点开始删除一定是最优解,如果在当前情况下仍然无法删除所有点,则输出NO。

    写的很撮的代码,去看别人的代码,发现他们写的都比我好

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <vector>
    #include <cstring>
    #include <iomanip>
    #include <set>
    #include<ctime>
    //CLOCKS_PER_SEC
    #define se second
    #define fi first
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define Pii pair<int,int>
    #define Pli pair<ll,int>
    #define ull unsigned long long
    #define pb push_back
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    const int N=4e5+5;
    const ull base=163;
    const int INF=0x3f3f3f3f;
    using namespace std;
    int head[N],nx[N],to[N];
    int tot=1;
    struct node {
        int le,du,num;
        friend bool operator < (node a, node b){
            if(a.le==b.le)
            {
                return a.du>b.du;
            }
            return a.le>b.le;
        }
    }L[N];
    void add(int u,int v){
        to[tot]=v;
        nx[tot]=head[u];
        head[u]=tot++;
    }
    int dfs(int x,int pre){
        for(int i=head[x];i;i=nx[i]){
            int v=to[i];
            if(v==pre)continue;
            if(v!=pre)L[x].le+=dfs(v,x);
        }
        return L[x].le;
    }
    bool vis[N];
    vector<int>ans;
    int main(){
        fio;
        int n;
        cin>>n;
        int S=-1;
        for(int i=1;i<=n;i++){
            int x;
            cin>>x;
            if(x==0){
                S=i;
                continue;
            }
            add(i,x);
            add(x,i);
            L[i].du++,L[x].du++;
            L[i].le=1;
            L[i].num=i;
        }
        if(n%2==0)return cout<<"NO
    ",0;
        L[S].le=1;
        L[S].num=S;
        dfs(S,S);
        priority_queue<node>q;
        for(int i=1;i<=n;i++){
            if(L[i].du%2==0)
                q.push(L[i]);
        }
        while(!q.empty()){
            node x=q.top();
            q.pop();
            if(vis[x.num]||L[x.num].du%2==1)continue;
            vis[x.num]=1;
            ans.pb(x.num);
            for(int i=head[x.num];i;i=nx[i]){
                int v=to[i];
                if(L[v].du)L[v].du--;
                if(L[v].du==0&&vis[v]==0){
                    vis[v]=1;
                    ans.pb(v);
                }
                else if(L[v].du%2==0&&!vis[v]){
                    q.push(L[v]);
                }
            }
        }
        if(ans.size()==n){
            cout<<"YES"<<endl;
            for(auto i:ans){
                cout<<i<<endl;
            }
        }
        else cout<<"NO"<<endl;
        return 0;
    }
  • 相关阅读:
    GridView动态创建TemplateField的回发问题
    ASP.NET页面生命周期
    php图片叠加
    php文件下载
    mysql 常用操作命令
    转载:图解SQL的Join
    利用iframe来做无刷新上传
    php抽象和接口的区别
    php 循环打开目录读取文件
    mysql存储引擎的对比(一)
  • 原文地址:https://www.cnblogs.com/Mrleon/p/8878101.html
Copyright © 2020-2023  润新知