zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",finans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    算法导论第11章 散列表
    Ubuntu14.04上安装Jupyter的方法
    WinSCP连接远程的Ubuntu失败
    K-means和K-means++好的网站
    Ubuntu14.04上安装pip的方法
    算法导论第一章
    微服务架构的特点
    国内maven仓库地址 || 某个pom或者jar找不到的解决方法
    REST or RPC?
    zookeeper安装及环境变量设置
  • 原文地址:https://www.cnblogs.com/Przz/p/5812349.html
Copyright © 2011-2022 走看看