hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)

Mart Master II

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 675    Accepted Submission(s): 237

Problem Description

Trader Dogy lives in city S, which consists of n districts. There are n - 1 bidirectional roads in city S, each connects a pair of districts. Indeed, city S is connected, i.e. people can travel between every pair of districts by roads.

In some districts there are marts founded by Dogy’s competitors. when people go to marts, they’ll choose the nearest one. In cases there are more than one nearest marts, they’ll choose the one with minimal city number.

Dogy’s money could support him to build only one new marts, he wants to attract as many people as possible, that is, to build his marts in some way that maximize the number of people who will choose his mart as favorite. Could you help him?

Input

There are multiple test cases. Please process till EOF.

In each test case:

First line: an integer n indicating the number of districts.

Next n - 1 lines: each contains three numbers bi, ei and wi, (1 ≤ bi,ei ≤ n,1 ≤ wi ≤ 10000), indicates that there’s one road connecting city bi and ei, and its length is wi.

Last line : n(1 ≤ n ≤ 105) numbers, each number is either 0 or 1, i-th number is 1 indicates that the i-th district has mart in the beginning and vice versa.

Output

For each test case, output one number, denotes the number of people you can attract, taking district as a unit.

Sample Input

5
1 2 1
2 3 1
3 4 1
4 5 1
1 0 0 0 1
5
1 2 1
2 3 1
3 4 1
4 5 1
1 0 0 0 0
1
1
1
0

Sample Output

2
4
0
1

/*
hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi‘an Online)

problem:
有n个城市,有的城市有集市. 城市会选择离他最近,编号最小的集市.  如果再建一个集市,那么最多有多少个城市会来这

solve:
如果 城市v的人要到新的集市u 那么dis(u,v) < dis(v,z).(z为原先离v最近的集市)
所以可以先用最短路求出所有城市的最近集市的距离和编号.
如果用dis表示到根节点的距离,那么 dis[u] + dis[v] < spfa(v,z) ---->  dis[u] < dis[v]-spfa(v,z)
所以就成了:求对u而言满足这个公式的点的个数.

hhh-2016-08-24 16:17:48
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <map>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfl(a) scanf("%I64d",&a)
#define key_val ch[ch[root][1]][0]
#define inf 0x3f3f3f3f
#define mod 1000003
using namespace std;
const int maxn = 100010;
int head[maxn];
int n,k,s[maxn],f[maxn],root,is[maxn];
int Size,tot,u,v,w;
bool vis[maxn];
ll ans[maxn];
ll finans = 0;
ll val;
struct node
{
    int to,w;
    int next;
} edge[maxn << 2];

void ini()
{
    clr(head,-1);
    clr(s,0),clr(ans,0);
    tot = 0;
}

void add_edge(int u,int v,int w)
{
    edge[tot].to = v,edge[tot].w = w,edge[tot].next = head[u],head[u] = tot++;
}
pair<int,int> tp[maxn];

void spfa()
{
    memset(vis,0,sizeof(vis));
    queue<int>q;
    for(int i =1; i <= n; i++)
    {
        if(is[i])
        {
            tp[i] = make_pair(0,i);
            vis[i] = 1;
            q.push(i);
        }
        else
        {
            tp[i] = make_pair(inf,i);
        }
    }
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for(int i = head[u]; ~i ; i = edge[i].next)
        {
            int v = edge[i].to;
            if(tp[v].first > tp[u].first + edge[i].w)
            {
                tp[v].first = tp[u].first + edge[i].w;
                tp[v].second = tp[u].second;
                if(!vis[v])
                {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
}

void get_root(int now,int fa)
{
    int v;
    s[now] = 1,f[now] = 0;
    for(int i = head[now]; ~i; i = edge[i].next)
    {
        if((v=edge[i].to) == fa || vis[v])
            continue;
        get_root(v,now);
        s[now] += s[v];
        f[now] = max(f[now],s[v]);
    }
    f[now] = max(f[now],Size-s[now]);
    if(f[now] < f[root]) root = now;
}
int num;
int seq[maxn];
int d[maxn];
void dfs(int now,int fa)
{
    int v;
    seq[num++] = now;
    s[now] = 1;

    for(int i = head[now]; ~i; i = edge[i].next)
    {
//        cout << edge[i].to << " " <<vis[edge[i].to]<<" " << fa <<endl;
        if( (v=edge[i].to) == fa || vis[v])
            continue;
        d[v] = d[now] + edge[i].w;
        dfs(v,now);
        s[now] += s[v];
    }
}
pair<int,int>t[maxn];
void cal(int now,int ob)
{
    num = 0;
    d[now] = ob;
    dfs(now,0);
//    cout <<"root:" << now <<endl;
    for(int i=0; i < num; i++)
    {
//        cout << tp[seq[i]].first-d[seq[i]] << " ";
        t[i] = make_pair(tp[seq[i]].first-d[seq[i]],tp[seq[i]].second);
    }
//    cout <<endl;
//    for(int i = 0;i < num ;i++)
//    {
//        cout << d[seq[i]] << " ";
//    }
//    cout <<endl;
    sort(t,t+num);

    for(int i = 0; i < num; i++)
    {
        if(is[seq[i]])
            continue;
        pair<int,int> temp = make_pair(d[seq[i]],seq[i]);
        int pos = lower_bound(t,t+num,temp)-t;
//        cout << num <<" " <<pos <<endl;
        if(!ob)
        ans[seq[i]] += (ll)(num - pos);
        else
            ans[seq[i]] += (ll)(pos - num);
    }
}

void make_ans(int now,int cnt)
{
    int v ;
    f[0] = Size = cnt;
    get_root(now,root = 0);

    cal(root,0);
    vis[root] = 1;
    for(int i = head[root]; ~i ; i = edge[i].next)
    {
        if( vis[v = edge[i].to] )
            continue;
        cal(v,edge[i].w);
        make_ans(v,s[v]);
    }
}

int main()
{
//    freopen("in.txt","r",stdin);
    while( scanfi(n) != EOF)
    {
        ini();
        finans = 0;
        for(int i = 1; i < n; i++)
        {
            scanfi(u),scanfi(v),scanfi(w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        for(int i =1; i<= n; i++)
            scanfi(is[i]);
        spfa();
//        for(int i = 1;i <= n;i++)
//        {
//            printf("%d %d\n",tp[i].first,tp[i].second);
//        }
        memset(vis,0,sizeof(vis));
        make_ans(1,n);
        for(int i = 1;i <=n;i++)
        {
            finans = max(finans,ans[i]);
        }
//        cout <<"ans";
        printf("%I64d\n",finans);
    }
    return 0;
}

  

hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)

时间: 2024-10-10 16:41:09

hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)的相关文章

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

hdu 5008(2014 ACM/ICPC Asia Regional Xi&#39;an Online ) Boring String Problem(后缀数组&amp;二分)

Boring String Problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 219    Accepted Submission(s): 45 Problem Description In this problem, you are given a string s and q queries. For each que

2014 ACM/ICPC Asia Regional Xi&#39;an Online(HDU 5007 ~ HDU 5017)

题目链接 A题:(字符串查找,水题) 题意 :输入字符串,如果字符串中包含“ Apple”, “iPhone”, “iPod”, “iPad” 就输出 “MAI MAI MAI!”,如果出现 “Sony” 就输出“SONY DAFA IS GOOD!” ,大小写敏感. 思路 : 字符串查找,水题. 1 #include <string.h> 2 #include <stdio.h> 3 #include <iostream> 4 5 using namespace st

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;

HDU 5010 Get the Nut(2014 ACM/ICPC Asia Regional Xi&#39;an Online)

思路:广搜, 因为空格加上动物最多只有32个那么对这32个进行编号,就能可以用一个数字来表示状态了,因为只有 ‘P’   'S' 'M' '.' 那么就可以用4进制刚好可以用64位表示. 接下去每次就是模拟了. 注意:  ‘S’ 不是只有一个. 一个东西如果不是'P'在动的话要先判断周围有没有‘P’,有的话要先吃掉      'P'在动的时候如果一个位置周围有多个东西,都要吃掉. #include<iostream> #include<cstdio> #include<alg

2014 ACM/ICPC Asia Regional Xi&#39;an Online 233 Matrix,hdu 5015

比赛的时候若是这题过了就进前50 刚开始的时候大家的思路都以为是找规律的题目,于是再推公式,此外还发现类似于杨辉三角.于是又去套杨辉三角的通项去求. 于是TLE了无数次.(每次取范围的最大值也要3s多). 对于明显的矩阵样子,其实可以转化为矩阵的运算,每一行的转移.就是对一个转移矩阵的幂运算.然后再用快速矩阵幂即可. A: 10 0 0 1 10 1 0 1 10 1 1 1 0  0  0 1 B: 23 0 0 3 C=A^M  *B,ans=C[N] 教训:对于时间限制,即便是最大数据也要

2014 ACM/ICPC Asia Regional Xi&#39;an Online

03 hdu5009 状态转移方程很好想,dp[i] = min(dp[j]+o[j~i]^2,dp[i]) ,o[j~i]表示从j到i颜色的种数. 普通的O(n*n)是会超时的,可以想到o[]最大为sqrt(n),问题是怎么快速找到从i开始往前2种颜色.三种.四种...o[]种的位置. 离散化之后,可以边走边记录某个数最后一个出现的位置,初始为-1,而所要求的位置就等于 if(last[a[i]]==-1) 该数没有出现过,num[i][1] = i,num[i][j+1] = num[i-1

HDU 4998 Rotate 计算几何 2014 ACM/ICPC Asia Regional Anshan Online

题意: 有一个平面放在一个二维坐标轴上 给定n个操作 (x,y) p 表示把平面绕着(x,y) 逆时针转p弧度. 最后的结果相当于平面绕着(X, Y) 逆时针旋转了P弧度. 求:X,Y,P 思路: 任取一个三角形ABC,然后根据n个操作得到A'B'C', 然后求外心. 旋转的角度就是相加..==为啥我也不大清楚,不是本弱写的. #include <cstdio> #include <algorithm> #include <iostream> #include <

HDU 5000 2014 ACM/ICPC Asia Regional Anshan Online DP

Clone Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/65536K (Java/Other) Total Submission(s) : 8   Accepted Submission(s) : 5 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description After eating food from Chernobyl,