贪心+拓扑排序 AOJ 2456 Usoperanto

题目传送门

题意:给出一条链,比如x连到y,x一定要在y的左边,且代价是这条链经过的点的权值和,问如何排序使得代价最小

分析:类似拓扑排序,先把入度为0的点入队,把指向该点的所有点按照权值排序,保证这样是代价是最小的,然后把这一块看成一个点继续入队。看图更简单:

/************************************************
* Author        :Running_Time
* Created Time  :2015/10/3 星期六 13:02:41
* File Name     :J.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e6 + 10;
const int E = 2e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-8;
struct Edge {
    int v, nex;
}edge[E];
int fa[N], head[N], in[N];
int w[N], sta[N];
int n, e;
ll ans;

void init(void) {
    memset (head, -1, sizeof (head));
    memset (in, 0, sizeof (in));
    e = 0;
}

void add_edge(int u, int v) {
    edge[e].v = v;  edge[e].nex = head[u];
    head[u] = e++;
}

void BFS(void) {
    queue<int> Q;
    for (int i=0; i<n; ++i) {
        if (!in[i]) {
            Q.push (i);
        }
    }
    while (!Q.empty ()) {
        int u = Q.front (); Q.pop ();
        int tot = 0;
        for (int i=head[u]; ~i; i=edge[i].nex)  {
            int v = edge[i].v;
            sta[tot++] = w[v];
        }
        sort (sta, sta+tot);
        for (int i=0; i<tot; ++i)   {
            ans += 1ll * sta[i] * (tot - i - 1);
        }
        if (fa[u] == -1)    continue;
        w[fa[u]] += w[u];
        if (! (--in[fa[u]]))    {
            Q.push (fa[u]);
        }
    }
}

int main(void)    {
    while (scanf ("%d", &n) == 1)   {
        init ();
        for (int i=0; i<n; ++i) {
            scanf ("%d%d", &w[i], &fa[i]);
            if (fa[i] != -1)    {
                in[fa[i]]++;
                add_edge (fa[i], i);
            }
        }
        ans = 0;
        BFS ();
        printf ("%lld
", ans);
    }

    return 0;
}

  

编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4853395.html