题目链接:http://acm.bnu.edu.cn/v3/problem_show.php?pid=39572
题目详细分析:http://talk.icpc-camp.org/d/127-jag-summer-2012-day-4-j-usoperanto
对于这个题目,自己的一点补充(bfs 拓扑排序):在建树的时候,每建立一条边,父亲节点出度+1,因此树叶子节点的出度是为0的(题解里说的入度其实就是在建边的时候父亲节点的出度);那么把所有出度为0的节点压入队列,然后计算这些出度为0的节点u对ans的贡献,同时把u这个节点的单词长度加到父亲节点,相当于dfs树形dp统计子树单词总长度的过程。依此拓扑(拓扑有两种方式,一种是从根节点开始,一种是从叶子节点开始)。
/************************************************************** Problem:bnu 39572 User: youmi Language: C++ Result: Accepted Time:31 ms Memory:38704 KB ****************************************************************/ #pragma comment(linker, "/STACK:1024000000,1024000000") //#include<bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <stack> #include <set> #include <sstream> #include <cmath> #include <queue> #include <deque> #include <string> #include <vector> #define zeros(a) memset(a,0,sizeof(a)) #define ones(a) memset(a,-1,sizeof(a)) #define sc(a) scanf("%d",&a) #define sc2(a,b) scanf("%d%d",&a,&b) #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scs(a) scanf("%s",a) #define sclld(a) scanf("%I64d",&a) #define pt(a) printf("%d\n",a) #define ptlld(a) printf("%I64d\n",a) #define rep0(i,n) for(int i=0;i<n;i++) #define rep1(i,n) for(int i=1;i<=n;i++) #define rep_1(i,n) for(int i=n;i>=1;i--) #define rep_0(i,n) for(int i=n-1;i>=0;i--) #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define lson (step<<1) #define rson (lson+1) #define esp 1e-6 #define oo 0x3fffffff #define TEST cout<<"*************************"<<endl using namespace std; typedef long long ll; int n; const int maxn=1000000+10; int dp[maxn]; int fa[maxn]; int out[maxn]; struct node { int v,next; }e[maxn]; struct point { int dp,id; point(int a,int b):dp(a),id(b){}; }; struct cmp { bool operator() (const struct point a,const struct point b) { return a.dp>b.dp; } }; priority_queue<struct point ,vector<struct point>, cmp>q; int head[maxn]; int T; void init() { T=0; ones(head); zeros(fa); while(!q.empty()) q.pop(); } void build(int u,int v) { e[T].v=v; e[T].next=head[u]; head[u]=T++; } ll ans; void solve() { queue<int >p; for(int i=0;i<=n;i++) if(out[i]==0) p.push(i); while(!p.empty()) { int u=p.front(); p.pop(); dp[fa[u]]+=dp[u]; for(int i=head[u];~i;i=e[i].next) { int v=e[i].v; q.push(point(dp[v],v)); } while(!q.empty()) { struct point temp=q.top(); q.pop(); int v=temp.id; //printf("u->%d v->%d \n",u,v); ans+=1ll*dp[v]*q.size(); } if(fa[u]!=0) if(--out[fa[u]]==0) p.push(fa[u]); } } int main() { //freopen("in.txt","r",stdin); while(~sc(n)) { int u,v; init(); dp[0]=0; rep1(i,n) { sc2(u,v); dp[i]=u; v++; fa[i]=v; out[fa[i]]++; build(v,i); } ans=0; solve(); printf("%lld\n",ans); } return 0; }
不为失败找借口,只为成功找方法