zoukankan      html  css  js  c++  java
  • 贪心+拓扑排序 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;
    }
    

      

    编译人生,运行世界!
  • 相关阅读:
    socket错误码获取
    代码整洁之道读书笔记函数
    算法学习之堆排序
    包含与继承区别
    提高 LayerBacked Memory Use
    RenderBuffer
    算法学习之快速排序
    NSTimer
    DNS and BIND ... (转载) zhumao
    Samba学习笔记(转载) zhumao
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4853395.html
Copyright © 2011-2022 走看看