BZOJ 4567 [SCOI2016] back word (Trie tree, greedy)

Topic links: https://www.lydsy.com/JudgeOnline/problem.php?id=4567

Solution: Clearly the answer must be less than \ (the n-\ the n-Times \) , reverse the string prefix become built Trie, that Italy transformed as follows:

Every time you can mark a point in a tree, marking one point required before all its ancestors are marked, mark a point value equal to its father marked time, and maximize the value (it can also be a father and son find all the marks of time and the difference between the minimum value)

A saw this mind immediately jumped out of a greedy: the election in accordance with the number of small to son (with a heap maintenance)

However wrong

hack data:

10
aaa
baa
caa
daa
eaa
aa
a
b
ab
bb

The program is based on the right sub-tree size from small to elections. Here are a do not know (the other is actually a patchwork solution to a problem the Internet) to prove wrong:

(1) the optimal answer must DFS order. The difference between father and son according to time and to understand, quite obviously. (Sorry for my limited level will also be able Speaking of this sake ......)

(2) DFS preface optimal answer must be by sub-tree size from small to elections. Emotional understanding is: Because it is DFS order that we can only consider the contribution of roots to produce an answer, minimizing the difference between the root of all its sons and time. Then there is the equivalent of a bunch of their number to make ordering and minimum prefix and then it is clear that the ......

Lesson: greedy this kind of thing must not be taken for granted, we must prove that! To prove! To prove!

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define llong long long
using namespace std;

const int N = 1e5;
const int L = 5e5+1e4;
const int S = 26;
struct Edge
{
    int v,nxt;
} e[(N<<1)+3];
int son[L+3][S+1];
char str[L+3];
bool isky[L+3];
int sz[N+3];
int sonn[N+3];
int fe[N+3];
int fa[N+3];
struct Element
{
    int u;
    Element() {}
    Element(int _u) {u = _u;}
    bool operator <(const Element &arg) const
    {
        return sz[u]>sz[arg.u];
    }
};
priority_queue<Element> que;
int n,siz,nn,en;

void insertstr(char str[],int len)
{
    int u = 1;
    for(int i=1; i<=len; i++)
    {
        if(!son[u][str[i]]) {siz++; son[u][str[i]] = siz;}
        u = son[u][str[i]];
    }
    isky[u] = true;
}

void addedge(int u,int v)
{
    printf("addedge %d %d\n",u,v);
    en++; e[en].v = v;
    e[en].nxt = fe[u]; fe[u] = en;
}

void dfs0(int u,int anc)
{
    if(isky[u]) {nn++; addedge(nn,anc); addedge(anc,nn); sonn[anc]++; anc = nn;}
    for(int i=1; i<=S; i++)
    {
        int v = son[u][i];
        if(v)
        {
            dfs0(v,anc);
        }
    }
}

void dfs(int u)
{
    sz[u] = 1;
    for(int i=fe[u]; i; i=e[i].nxt)
    {
        if(e[i].v==fa[u]) continue;
        fa[e[i].v] = u;
        dfs(e[i].v);
        sz[u] += sz[e[i].v];
    }
}

int main()
{
    siz = 1;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",str+1); int len = strlen(str+1);
        for(int j=1; j<=len; j++) str[j] -= 96;
        for(int j=1; j<=len+1-j; j++) swap(str[j],str[len+1-j]);
        insertstr(str,len);
    }
    nn = 1; dfs0(1,1);
    dfs(1);
    que.push(Element(1));
    llong ans = 0ll;
    for(int i=1; i<=nn; i++)
    {
        int u = que.top().u; que.pop();
        printf("%d\n",u);
        ans += sonn[u]*(i-1ll);
        for(int j=fe[u]; j; j=e[j].nxt)
        {
            if(e[j].v==fa[u]) continue;
            fa[e[j].v] = u;
            que.push(e[j].v);
        }
    }
    ans = n*(n+1ll)/2ll-ans;
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11041682.html