zoukankan      html  css  js  c++  java
  • poj 2114 Boatherds

    Boatherds
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 3588   Accepted: 1159

    Description

    Boatherds Inc. is a sailing company operating in the country of Trabantustan and offering boat trips on Trabantian rivers. All the rivers originate somewhere in the mountains and on their way down to the lowlands they gradually join and finally the single resulting river flows to the sea. Moreover, the Trabantian villages are exactly at the rivers' springs, junctions and at the mouth of the largest river. Please note that more than 2 rivers can join at a junction. However, the rivers always form a tree (with villages as vertices). 

    The pricing policy of the Boatherds is very simple: each segment of each river between two villages is assigned a price (the price is same in both directions), so if a tourist requests a journey between any two villages, the ticket office clerks just add the prices of the segments along the only path between the villages. 

    One day, a very strange tourist appeared. She told the clerks that she returns to her country on the next day and she wants to spend all the remaining money on a boat trip, so they should find a route with exactly this cost. Being just poor (ahem) businessmen, they have asked the Abacus Calculator Makers for help. 

    You are given a description of the river network with costs of river segments and a sequence of integers x1,..., xk. For each xi, you should determine if there is a pair of cities (a, b) in the river network such that the cost of the trip between a and b is exactly xi. 

    Input

    The input consists of several instances. Each instance is described by (in the following order): 
    • A single line containing a single integer: the number of villages N (1 <= N <= 10 000). 
    • N lines describing the villages. The i-th of these lines (1 <= i <= N) describes the village with number i. It contains space separated integers d1, c1, d2, c2, , dki, cki, 0. The dj's are numbers of villages from which the rivers flow directly to the village i (with no other villages in between), each cj is the price of the journey between villages i and dj. Moreover, 2 <= dj <= N and 0 <= cj <= 1 000. Village 1 always corresponds to the mouth of the largest river, therefore no di can ever be equal to 1. 
    • M <= 100 lines describing the queries. The i-th of these lines corresponds to the i-th query and contains a single integer xi (1 <= xi <= 10 000 000). 
    • The instance is finished by a single line containing the number 0.

    The whole input is ended by a single line containing the number 0. 

    Output

    For each instance you should produce a sequence of M lines (where M is the number of queries in the particular instance). The i-th of these lines contains the word "AYE" if there exists a pair of cities in the river network which is connected by a path of cost xi, or the word "NAY" otherwise. 

    Output for each instance must be followed by a single line containing just the dot character. 

    Sample Input

    6
    2 5 3 7 4 1 0
    0
    5 2 6 3 0
    0
    0
    0
    1
    8
    13
    14
    0
    0
    

    Sample Output

    AYE
    AYE
    NAY
    AYE
    .

    题意:判断树上是否有两点的距离正好等于K
    思路:分治法:树上的重心分解

    AC代码:
    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    #include<string>
    #include <utility>
    #include<cmath>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int N_MAX = 10000 + 20;
    struct edge {
        int to, length;
        edge(int to=0,int length=0):to(to),length(length) {}
    };
    int n, k;
    bool centroid[N_MAX];
    int subtree_size[N_MAX];
    int ans; 
    vector<edge>G[N_MAX];
    void init( int n) {
        for (int i = 1; i <= n; i++) { G[i].clear(); }
        //memset(subtree_size,0,sizeof(subtree_size)); 
    }
    int compute_subtree_size( int v, int p) {
        int c = 1;
        for (int i = 0; i < G[v].size();i++) {
            int w = G[v][i].to;
            if (w == p ||  centroid[w])continue;
            c += compute_subtree_size(w, v);
        }
        subtree_size[v] = c;
        return c;
    }
    
    
    pair<int, int>search_centroid( int v,int p, int t) {
        pair<int, int>res = make_pair(INF,-1);
        int s = 1,m=0;
        for (int i = 0; i < G[v].size(); i++) {
            int w = G[v][i].to;
            if (w == p || centroid[w])continue;
            res = min(res, search_centroid(w, v, t));
            m = max(m, subtree_size[w]);
            s += subtree_size[w];
        }
        m = max(m, t - s);
        res = min(res,make_pair(m,v));
        return res;
    }
    
    void enumerate_paths( int v, int p, int d,vector<int>&ds) {
        ds.push_back(d);
        for (int i = 0; i < G[v].size();i++) {
            int w = G[v][i].to;
            if (w == p ||  centroid[w])continue;
            enumerate_paths(w,v,d+G[v][i].length,ds);
        }
    }
    
    int count_pairs(vector<int>&ds) {
        int res = 0;
        sort(ds.begin(), ds.end());
        int j = ds.size();
        for (int i = 0; i <ds.size();i++) {
            while (j > 0 && ds[i] + ds[j-1] > k)j--;
            res += j - (j > i ? 1 : 0);
        }
        j = ds.size();
        for (int i = 0; i < ds.size();i++) {
            while (j > 0 && ds[i] + ds[j - 1] >= k)j--;
            res -= j - (j > i ? 1 : 0);
        }
        return res;
    }
    void solve_subproblem( int v) {                                                                                                            
        compute_subtree_size(v, -1);
        int s = search_centroid(v, -1, subtree_size[v]).second;
        centroid[s] = true;
        for (int i = 0; i < G[s].size();i++) {
            if (centroid[G[s][i].to])continue;
            solve_subproblem(G[s][i].to);
        }
        static vector<int>ds;
        ds.clear();
        ds.push_back(0);
        for (int i = 0; i < G[s].size();i++) {
            if (centroid[G[s][i].to])continue;
            static vector<int>tds;
            tds.clear();
            enumerate_paths(G[s][i].to,s,G[s][i].length,tds);
            ans -= count_pairs(tds);
            ds.insert(ds.end(), tds.begin(), tds.end());
        }
        ans += count_pairs(ds);
        centroid[s] = false;
    }
    
    int main() {
        while (scanf("%d",&n)&&n) {
            init(n);
            for (int i = 1; i <= n;i++) {
                int to, cost;
                while (scanf("%d", &to) && to) {
                    scanf("%d",&cost);
                    G[i].push_back(edge (to,cost ));
                    G[to].push_back(edge( i,cost ));
                }
            }
            while (scanf("%d",&k)&&k) {
                ans = 0;
                solve_subproblem(1);
                puts(ans>0?"AYE":"NAY");
            }
            puts(".");
        }
        return 0;
    }
  • 相关阅读:
    动态显示隐藏的kindeditor 编辑器,如何获取焦点
    BT修改默认端口
    fa内容重复度检测
    fa后台总是提示 未知的数据格式,以及调试方法大全
    vscode这种界面是怎么回事?我丢你楼某
    腾讯云服务器,安装BT面板
    fastadmin编辑器配置,类比wangeditor
    fastadmin 安装过插件以后,原始插件的文件能不能删除?
    leetcode——65. 有效数字
    leetcode——8. 字符串转换整数 (atoi)
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/9064499.html
Copyright © 2011-2022 走看看