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;
    }
    
  • 相关阅读:
    PHP sessions that have already been started
    DOM对象和JQuery对象的区别
    iOS在支持arc的工程中,导入不支持arc的第三方的插件
    Android下利用RadioGroup和RadioButton实现Tabbar的效果
    iOS7.1以后企业应用发布需要HTTPS协议,解决步骤
    Scrapy基础(四)————Scrapy的使用Pycharm进行Debuge设置
    Scrapy基础(三) ------xpath基础
    Scrapy基础(二)————Scrapy的安装和目录结构
    python基础一 ------Python 的编码
    Scrapy基础(一) ------学习Scrapy之前所要了解的
  • 原文地址:https://www.cnblogs.com/tarjan/p/7495577.html
Copyright © 2011-2022 走看看