题目链接: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;
}

 

posted on 2015-10-03 23:21  中子星  阅读(397)  评论(0编辑  收藏  举报