HDU 5016 Mart Master II

Mart Master II

Time Limit: 6000ms

Memory Limit: 65536KB

This problem will be judged on HDU. Original ID: 5016
64-bit integer IO format: %I64d      Java class name: Main

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

解题:挺恶心的一道题

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 using PII = pair<int,int>;
  4 const int maxn = 100010;
  5 const int INF = ~0u>>2;
  6 PII d[3][maxn];
  7 struct arc {
  8     int to,w,next;
  9     arc(int x = 0,int y = 0,int z = -1) {
 10         to = x;
 11         w = y;
 12         next = z;
 13     }
 14 } e[maxn<<1];
 15 int head[maxn],sz[maxn],maxson[maxn],mart[maxn],tot,cnt,n;
 16 int ans[maxn];
 17 void add(int u,int v,int w) {
 18     e[tot] = arc(v,w,head[u]);
 19     head[u] = tot++;
 20 }
 21 queue<int>q;
 22 bool done[maxn];
 23 void spfa() {
 24     memset(done,false,sizeof done);
 25     while(!q.empty()){
 26         int u = q.front();
 27         q.pop();
 28         done[u] = false;
 29         for(int i = head[u]; ~i; i = e[i].next){
 30             PII tmp(d[0][u].first + e[i].w,d[0][u].second);
 31             if(d[0][e[i].to] > tmp){
 32                 d[0][e[i].to] = tmp;
 33                 if(!done[e[i].to]){
 34                     done[e[i].to] = true;
 35                     q.push(e[i].to);
 36                 }
 37             }
 38         }
 39     }
 40 }
 41 int dfs(int u,int fa){
 42     sz[u] = 1;
 43     maxson[u] = 0;
 44     for(int i = head[u]; ~i; i = e[i].next){
 45         if(e[i].to == fa || done[e[i].to]) continue;
 46         dfs(e[i].to,u);
 47         sz[u] += sz[e[i].to];
 48         maxson[u] = max(maxson[u],sz[e[i].to]);
 49     }
 50     return sz[u];
 51 }
 52 int root(const int sum,int u,int fa){
 53     int ret = u;
 54     maxson[u] = max(maxson[u],sum - sz[u]);
 55     for(int i = head[u]; ~i; i = e[i].next){
 56         if(e[i].to == fa || done[e[i].to]) continue;
 57         int x = root(sum,e[i].to,u);
 58         if(maxson[x] < maxson[ret]) ret = x;
 59     }
 60     return ret;
 61 }
 62 void update(int u,int w,int fa){
 63     d[1][cnt] = PII(w,u);
 64     d[2][cnt++] = PII(d[0][u].first - w,d[0][u].second);
 65     for(int i = head[u]; ~i; i = e[i].next){
 66         if(e[i].to == fa || done[e[i].to]) continue;
 67         update(e[i].to,w + e[i].w,u);
 68     }
 69 }
 70 void calc(int u,int w,int sg){
 71     cnt = 0;
 72     update(u,w,0);
 73     sort(d[2],d[2] + cnt);
 74     for(int i = 0; i < cnt; ++i){
 75         if(mart[d[1][i].second]) continue;
 76         auto it = lower_bound(d[2],d[2] + cnt,d[1][i]) - d[2];
 77         ans[d[1][i].second] += (cnt - it)*sg;
 78     }
 79 }
 80 void solve(int u){
 81     int rt = root(dfs(u,0),u,0);
 82     done[rt] = true;
 83     calc(rt,0,1);
 84     for(int i = head[rt]; ~i; i = e[i].next){
 85         if(done[e[i].to]) continue;
 86         calc(e[i].to,e[i].w,-1);
 87     }
 88     for(int i = head[rt]; ~i; i = e[i].next){
 89         if(done[e[i].to]) continue;
 90         solve(e[i].to);
 91     }
 92 }
 93 int main() {
 94     int u,v,w;
 95     while(~scanf("%d",&n)) {
 96         memset(head,-1,sizeof head);
 97         int ret = tot = 0;
 98         for(int i = 1; i < n; ++i) {
 99             scanf("%d%d%d",&u,&v,&w);
100             add(u,v,w);
101             add(v,u,w);
102         }
103         for(int i = 1; i <= n; ++i) {
104             scanf("%d",mart + i);
105             if(mart[i]) {
106                 d[0][i] = PII(0,i);
107                 q.push(i);
108             } else d[0][i] = PII(INF,0);
109             ans[i] = 0;
110         }
111         spfa();
112         solve(1);
113         for(int i = 1; i <= n; ++i)
114             ret = max(ret,ans[i]);
115         printf("%d\n",ret);
116     }
117     return 0;
118 }

时间: 2024-10-06 13:03:45

HDU 5016 Mart Master II的相关文章

HDU 5016 Mart Master II (树上点分治)

题目地址:HDU 5016 先两遍DFS预处理出每个点距最近的基站的距离与基站的编号. 然后找重心,求出每个点距重心的距离,然后根据dis[x]+dis[y] < d[y],用二分找出当前子树中不会被占领的数量,总点数减去即是被占领的数量.这样就可以求出每个点最多占领的点的数量.然后找最大值即可. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue&g

【点分治】hdu5016 Mart Master II

点分治好题. ①手动开栈. ②dp预处理每个点被哪个市场控制,及其距离是多少,记作pair<int,int>数组p. ③设dis[u].first为u到重心s的距离,dis[u].second=u,到在统计的时候,若dis[u]<=(p[v].first-dis[v].first,p[v].second)(双关键字比较),则符合题意,当然这样在计算同一颗子树里的答案时,是压根不对的,但是既然这部分反正是要被减掉的,那就将错就错地计算即可了. ④最后在所有原非市场节点的ans中取一个最大的

hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi&#39;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

hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //最大流的灵活运用

3081 题意: n个女孩选择没有与自己吵过架的男孩有连边(自己的朋友也算,并查集处理),2分图,有些边,求有几种完美匹配(每次匹配每个点都不重复匹配) 我是建二分图后,每次增广一单位,(一次完美匹配),再修改起点还有终点的边流量,继续增广,直到达不到完美匹配为止.网上很多是用二分做的,我觉得没必要...(网上传播跟风真严重...很多人都不是真正懂最大流算法的...) 3277 : 再附加一条件,每个女孩可以最多与k个自己不喜欢的男孩.求有几种完美匹配(同上). 我觉得:求出上题答案,直接ans

HDU 2639 Bone Collector II(01背包变型)

此题就是在01背包问题的基础上求所能获得的第K大的价值. 具体做法是加一维去推当前背包容量第0到K个价值,而这些价值则是由dp[j-w[ i ] ][0到k]和dp[ j ][0到k]得到的,其实就是2个数组合并之后排序,但是实际做法最好不要怎么做,因为你不知道总共有多少种,而我们最多只需要前K个大的就行了(因为可能2个数组加起来的组合数达不到K个),如果全部加起来数组开多大不清楚,所以可以选用归并排序中把左右2个有序数组合并成一个有序数组的方法来做,就是用2个变量去标记2个有序数组的头,然后比

HDU 2830 Matrix Swapping II (DP,最大全1矩阵)

题意  给你一个n*m矩阵  每列都可以随便交换位置   求最优交换后最大的全1子矩阵 又是HDU 1505 1506的变种  但这个更容易了  因为每列都可以交换位置了   那么这一行中所有比i高的都可以与i相邻了  只需要统计这一行有多少个比i高就行了   可以在算出每一行后  把高度大的放前面去  用num[i]记录排序后的列原来的数  这样就有j列比h[i][num[j]]高了  最后的答案也就是max(j*h[i][num[j]]) #include<cstdio> #include

HDU 2830 Matrix Swapping II

给一个矩阵,依然是求满足条件的最大子矩阵 不过题目中说任意两列可以交换,这是对题目的简化 求出h数组以后直接排序,然后找出(col-j)*h[j]的最大值即可(这里的j是从0开始) 因为排序会影响到h数组下一行的求解,所以将h数组中的元素复制到temp数组中去,再排序 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algori

HDU 3081 Marriage Match II(二分法+最大流量)

HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个女孩n个男孩,每一个女孩能够和一些男孩配对.然后有些女孩是朋友.满足这个朋友圈里面的人,假设有一个能和某个男孩配对,其它就都能够,然后每轮要求每一个女孩匹配到一个男孩.且每轮匹配到的都不同,问最多能匹配几轮 思路:二分轮数k,然后建图为,源点连向女孩,男孩连向汇点容量都为k,然后女孩和男孩之间连边为.有关系的

HDU 3081 Marriage Match II(二分+最大流)

HDU 3081 Marriage Match II 题目链接 题意:n个女孩n个男孩,每个女孩可以和一些男孩配对,然后有些女孩是朋友,满足这个朋友圈里面的人,如果有一个能和某个男孩配对,其他就都可以,然后每轮要求每个女孩匹配到一个男孩,且每轮匹配到的都不同,问最多能匹配几轮 思路:二分轮数k,然后建图为,源点连向女孩,男孩连向汇点容量都为k,然后女孩和男孩之间连边为,有关系的连边容量1,这样一个匹配对应一条边,且不会重复,每次判断最大流是否等于n * k即可 代码: #include <cst