【codeforces 778C】 Peterson Polyglot

http://codeforces.com/problemset/problem/778/C (题目链接)

题意

  给出一个字典树,问删掉哪一层以后,得到的字典树最小。

Solution

  直接对于每一层进行讨论启发式合并暴力搞就好了。复杂度证明真是玄学。

细节

  注意根节点。

代码

// codeforces 778C
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=300010;
int head[maxn],size[maxn],deep[maxn],c[maxn][26];
int n,ans[maxn],cnt,sz;
char ch[10];
struct edge {int to,next;char w;}e[maxn<<1];

void link(int u,int v) {
	e[++cnt]=(edge){v,head[u],ch[0]};head[u]=cnt;
	e[++cnt]=(edge){u,head[v],ch[0]};head[v]=cnt;
}
int merge(int a,int b) {
	if (!a || !b) return a|b;
	int x=++sz;size[x]=1;
	for (int i=0;i<26;i++) {
		c[x][i]=merge(c[a][i],c[b][i]);
		size[x]+=size[c[x][i]];
	}
	return x;
}
void dfs(int x,int fa) {
	size[x]=1;
	for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) {
			deep[e[i].to]=deep[x]+1;
			c[x][e[i].w-'a']=e[i].to;
			dfs(e[i].to,x);
			size[x]+=size[e[i].to];
		}
	ans[deep[x]]+=size[x];sz=n;
	int p=0;
	for (int i=0;i<26;i++) p=merge(p,c[x][i]);
	ans[deep[x]]-=max(size[p],1);
}
int main() {
	scanf("%d",&n);
	for (int u,v,i=1;i<n;i++) {
		scanf("%d%d%s",&u,&v,ch);
		link(u,v);
	}
	dfs(1,0);
	int res=0;
	for (int i=0;i<n;i++) if (ans[i]>ans[res]) res=i;
	printf("%d
%d",n-ans[res],res+1);
	return 0;
}
原文地址:https://www.cnblogs.com/MashiroSky/p/6471914.html