zoukankan      html  css  js  c++  java
  • codeforces 778C. Peterson Polyglot(trie启发式合并,dfs,好题)

    题目链接

    题意:给出一棵 (n) 个结点 (m) 条边的 (trie) 树,树的深度从 (0) 开始,现要求删掉一层结点(删掉该层结点后下面的结点可能可以合并)使得剩下的点最少,输出最少的结点树并输出删除哪一层。

    题解:这一题直接暴力枚举删除 (i+1) 层,然后把 (i+2) 层的子树进行(trie)启发式合并,算合并后结点数即可。

    详见代码!

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    #define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int inf=0x3fffffff;
    const ll mod=1000000007;
    const int maxn=3e5+100;
    int head[maxn];
    struct edge
    {
        int to,next,w;
    }e[maxn*2];   //
    int tol=0;
    void add(int u,int v,int w)
    {
        e[++tol].to=v,e[tol].w=w,e[tol].next=head[u],head[u]=tol;
    }
    int ans[maxn];  //ans[i]表示删去deep[i]+1层减少的结点数目
    int sz[maxn*2],deep[maxn],c[maxn*2][27];
    int cnt;
    int n;
    
    int merge(int a,int b)
    {
        if(!a||!b) return a|b;  //当a或b为空结点时返回非空结点,全为空时返回0
        int rt=++cnt;
        sz[rt]=1;
        for(int i=0;i<26;i++)
        {
            c[rt][i]=merge(c[a][i],c[b][i]); //递归,这里要记录c[rt][i]结点值因为是多棵树两两合并
            sz[rt]+=sz[c[rt][i]];
        }
        return rt;
    }
    
    void dfs(int u,int f)
    {
        sz[u]=1;
        bool f1=false;  //判断结点u是否为叶子结点
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==f) continue;
            f1=true;
            deep[v]=deep[u]+1;
            c[u][e[i].w]=v;
            dfs(v,u);
            sz[u]+=sz[v];
        }
        ans[deep[u]]+=sz[u];
        cnt=n;
        int p=0;
        for(int i=0;i<26;i++) p=merge(p,c[u][i]);
        if(f1)
        ans[deep[u]]-=sz[p]; //当不是叶子结点时可以删去下一层
        else ans[deep[u]]-=1;  //当是叶子结点时不能删去下一层,此时对该层贡献的答案应该为0.
    }
    
    int main()
    {
        scanf("%d",&n);
        rep(i,1,n)
        {
            int u,v;
            char s[10];
            scanf("%d%d%s",&u,&v,s);
            add(u,v,s[0]-'a');
            add(v,u,s[0]-'a');
        }
        dfs(1,0);
        int p=0;
        rep(i,1,n) if(ans[i]>ans[p]) p=i;
        printf("%d
    %d
    ",n-ans[p],p+1);
        return 0;
    }
    
  • 相关阅读:
    黑马程序员面向对象09天1
    一键安装LNMP
    多屏互动技术
    阿里云CentOS 64位解决kernel2.6.32220.13.1.el6.x86_64 has missing requires错误
    listview的onItemClickListener失效
    在阿里云主机上基于CentOS用vsftpd搭建FTP服务器(赚)
    asp.net关于在线支付的实现过程
    C#关闭登录窗体,显示主窗体
    winform 刷新父窗体(转)
    用代码生成器生成的DAL数据访问操作类 基本满足需求了
  • 原文地址:https://www.cnblogs.com/tarjan/p/7495577.html
Copyright © 2011-2022 走看看