1002. [WZOI2011 S3] 周年纪念日

1002. [WZOI2011 S3] 周年纪念日

Problem 3 周年纪念日

(anniversary.pas/c/cpp)

背景

WZland即将迎来一个举国欢庆的日子—建国150亿周年纪念日,值此之际WZland有许多事情要准备……

问题描述

WZland的国王决定举办一个晚会,这次晚会要求所有的WZland居民都参加,但是他发现WZland的所有城市之间的道路都已经毁坏(平时WZland的居民都在自己的城市里活动,所以他们对于那些道路一点都不关心)。这是一件十分麻烦的事情,因为这个晚会要求所有居民都来参加,于是国王决定要重建道路。
他找出了WZland的地图,他发现WZland有N个城市,有M条破败的双向道路连接着这N个城市。由于周年纪念日就要到来,为了节省时间国王决定修建的道路恰好将这N个城市连接起来。修建一条长度为L的道路,需要花费L个Ws(Ws是WZland的通用货币),国王想要将总的花费降到最少,这样他能有足够多的钱来举办晚会。国王还有一个要求,因为这些道路是同时开始修建的,因此修建完这些道路的总时间等于修建完最长的那条道路的时间(你可以认为所有工人的修建速度是一样的,即一单位时间修建1单位长度的道路),国王想要总的修建时间最少。
由于要举行晚会,国王需要找到一个地点来举办晚会,这同样是一件十分麻烦的事情。因为WZland的每个人都十分懒,他们不愿意多走路(就连在这周年纪念日也不例外)。WZland的居民每走1单位长度的路就会产生1单位的不高兴度(这就是为什么他们都不愿离开自己城市的原因)。WZland的国王想要这个晚会的不高兴度尽量低(晚会的不高兴度就等于所有参加晚会的人的不高兴度的和),这就要求选取一个合适的地点来举办晚会(WZland的居民要通过即将修建好的道路,来到这个晚会举办地)。
举个例子,如果晚会在城市u举行,城市i有Pi个人,城市u和城市i的距离为D(u,i),那么这些人产生的不高兴度之和为Pi*D(u,i)。
国王把这个任务交给了你,他希望你能找出一个地点,是所有人的不高兴度之和最小。

输入格式

输入数据第一行包含两个整数N和M,表示WZland有N个城市,M条破坏的道路;
第2行到N+1行:第i+1行包含一个整数Pi,表示城市i的居民人数。
第N+2行到N+M+1行,每行三个整数A,B,L(1≤A,B≤N,A≠B),表示A和B之间有一条长度为L的破坏道路。

注意:两个城市之间可能会有多条道路。

输出格式

输出数据包含两行。
第一行两个整数C,T(用一个空格隔开),表示修建道路的最少花费和最少时间。
第二行两个整数U,H(用一个空格隔开),表示晚会的地点(如果有多个地点满足条件,输出编号最小的那个城市)和相应地点所有人的不高兴度之和。

样例输入输出

anniversary.in 
5 7
3
2
2
1
4
1 5 1
1 3 7
2 1 4
2 3 6
3 4 5
2 4 3
5 4 2

anniversary.out
11 5
5 29

样例解释

合法的修建方案如下图(相邻城市之间的距离和每个城市的人数见样例):

对题第一问 毫无疑问用kurskal就可以了

1e6的数据 prim是不行的

对于第二问 把最小生成树分离出来跑 树形dp

显然不能每个点都跑一次

我们需要从已知的点去更新其他的点

所以先从1跑一次dp

son数组 记录 他每个子树有多少节点

d数组记录当前节点的所有子树的节点 跑到这个节点的不高兴值

rout数组记录 从他父亲节点跑到这个节点的长度

dp数组 记录以每个节点为根的不高兴值

例如样例 假设我们已经更新到了dp[5]

拿下一个就是 dp[4]

dp[5]=people[1]*rout[5]+people[2]*rout[2]+people[3]*rout[3]+(peolpe[2]+people[3]+people[4])*rout[4];

dp[4]=people[1]*rout[5]+people[2]*rout[2]+people[3]*rout[3]+(people[1]+people[5])*rout[4];

显然 两个式子是有重叠部分的

我们可以看出 当前节点的不高兴值等于

它父亲节点的不高兴值减去当前节点son值到他父亲节点的路径

再加上剩余人数乘上从父亲节点到当前节点的路径

  1 #include <cstdio>
  2 #include <cctype>
  3 #include <algorithm>
  4
  5 typedef long long LL;
  6
  7 const LL INF=1e18*5;
  8 const int MAXN=100010;
  9
 10 int n,m;
 11
 12 int people[MAXN],fa[MAXN];
 13
 14 LL total;
 15
 16 LL d[MAXN],dp[MAXN],son[MAXN],rout[MAXN];
 17
 18 struct edge {
 19     int x,y;
 20     int val;
 21     friend bool operator < (edge a,edge b) {
 22         return a.val<b.val;
 23     }
 24 };
 25 edge e[MAXN<<1];
 26
 27 struct node {
 28     int to;
 29     int next;
 30     int val;
 31     node() {}
 32     node(int to,int val,int next):to(to),val(val),next(next) {}
 33 };
 34 node Edge[MAXN<<1];
 35
 36 int head[MAXN],tot;
 37
 38 inline void read(int&x) {
 39     int f=1;register char c=getchar();
 40     for(x=0;!isdigit(c);c==‘-‘&&(f=-1),c=getchar());
 41     for(;isdigit(c);x=x*10+c-48,c=getchar());
 42     x=x*f;
 43 }
 44
 45 inline void add(int x,int y,int val) {
 46     Edge[++tot]=node(y,val,head[x]);
 47     head[x]=tot;
 48     Edge[++tot]=node(x,val,head[y]);
 49     head[y]=tot;
 50 }
 51
 52 inline int find(int x) {
 53     if(x==fa[x]) return x;
 54     return fa[x]=find(fa[x]);
 55 }
 56
 57 inline void kurskal() {
 58     int cnt=0,mx=-1;
 59     LL sum=0;
 60     for(int i=1;i<=m;++i) {
 61         int xx=find(e[i].x);
 62         int yy=find(e[i].y);
 63         if(xx!=yy) {
 64             add(e[i].x,e[i].y,e[i].val);
 65             fa[xx]=yy;
 66             sum+=(LL)e[i].val;
 67             if(e[i].val>mx) mx=e[i].val;
 68             ++cnt;
 69             if(cnt==n-1) break;
 70         }
 71     }
 72     printf("%lld ",sum);
 73     printf("%d\n",mx);
 74     return;
 75 }
 76
 77 void DP(int now,int f) {
 78     son[now]=people[now];
 79     for(int i=head[now];i;i=Edge[i].next) {
 80         int v=Edge[i].to;
 81         if(v==f) continue;
 82         DP(v,now);
 83         son[now]+=son[v];
 84         rout[v]=Edge[i].val;
 85         d[now]+=(LL)(d[v]+(LL)son[v]*rout[v]);
 86     }
 87 }
 88
 89 void DP2(int now,int f) {
 90     dp[now]=dp[f]-(LL)(son[now]*rout[now])+(LL)((total-son[now])*rout[now]);
 91     for(int i=head[now];i;i=Edge[i].next) {
 92         int v=Edge[i].to;
 93         if(v==f) continue;
 94         DP2(v,now);
 95     }
 96 }
 97
 98 int hh() {
 99     freopen("anniversary.in","r",stdin);
100     freopen("anniversary.out","w",stdout);
101     read(n);read(m);
102     for(int i=1;i<=n;++i) fa[i]=i,read(people[i]),total+=people[i];
103     for(int i=1;i<=m;++i) read(e[i].x),read(e[i].y),read(e[i].val);
104     std::sort(e+1,e+1+m);
105     kurskal();
106     DP(1,0);
107     dp[1]=d[1];
108     for(int i=head[1];i;i=Edge[i].next) {
109         int v=Edge[i].to;
110         DP2(v,1);
111     }
112     LL ans=INF;
113     int pos;
114     for(int i=1;i<=n;++i)
115       if(dp[i]<ans) ans=dp[i],pos=i;
116     printf("%d %lld\n",pos,ans);
117     return 0;
118 }
119
120 int sb=hh();
121 int main(int argc,char**argv) {;}

代码

时间: 2024-10-03 21:42:16

1002. [WZOI2011 S3] 周年纪念日的相关文章

cogs——1001. [WZOI2011 S3] 消息传递

1001. [WZOI2011 S3] 消息传递 ★★   输入文件:messagew.in   输出文件:messagew.out   简单对比时间限制:1 s   内存限制:128 MB Problem 2 消息传递 (messagew.pas/c/cpp) 问题描述 WZland开办了一个俱乐部(这里面可以干任何的事情),这引来了许多的人来加入.俱乐部的人数越来越多,关系也越来越复杂…… 俱乐部的人来自各个地方,为了增加友谊,俱乐部举行了一次晚会.晚会上又进行了一个传话游戏,如果A认识B,

cojs 1001. [WZOI2011 S3] 消息传递

1001. [WZOI2011 S3] 消息传递 ★★   输入文件:messagew.in   输出文件:messagew.out   简单对比时间限制:1 s   内存限制:128 MB Problem 2 消息传递 (messagew.pas/c/cpp) 问题描述 WZland开办了一个俱乐部(这里面可以干任何的事情),这引来了许多的人来加入.俱乐部的人数越来越多,关系也越来越复杂…… 俱乐部的人来自各个地方,为了增加友谊,俱乐部举行了一次晚会.晚会上又进行了一个传话游戏,如果A认识B,

cogs 1001. [WZOI2011 S3] 消息传递 Tarjan

1001. [WZOI2011 S3] 消息传递 ★★   输入文件:messagew.in   输出文件:messagew.out   简单对比时间限制:1 s   内存限制:128 MB Problem 2 消息传递 (messagew.pas/c/cpp) 问题描述 WZland开办了一个俱乐部(这里面可以干任何的事情),这引来了许多的人来加入.俱乐部的人数越来越多,关系也越来越复杂…… 俱乐部的人来自各个地方,为了增加友谊,俱乐部举行了一次晚会.晚会上又进行了一个传话游戏,如果A认识B,

写在工作五周年纪念日

无论何时,请深爱陪伴在你身边的人,请努力去做自己喜欢的事情,请保持一颗坚强的心:当黑暗笼罩大地的时候你具有面对恐怖的勇气:当阳光出现在天际的那一刻,你能够享受温暖. 开始 2009 年的今天,我正式进入公司开始实习.尽管相隔五年,此刻想起来却一一在目,初出校门的农村孩子,面对陌生环境,对一切都充满好奇.然而天生的乡土气息使得自己没有什么胆量去发现周围的新鲜事物,只是循规蹈矩按照公司的实习流程一步一步认真的执行.那一刻,心中是一种从未有过的满足,尽量让自己表现得是个合格员工.每件事情都是小心翼翼,

(BC 一周年)hdu 5311 Hidden String

Hidden String Accepts: 437 Submissions: 2174 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) 问题描述 今天是BestCoder一周年纪念日. 比赛管理员Soda有一个长度为nn的字符串ss. 他想要知道能否找到ss的三个互不相交的子串s[l_1..r_1]s[l?1??..r?1??], s[l_2..r_2]s[l?2??..r?2

BestCoder 1st Anniversary ($) 1002.Hidden String

Hidden String Accepts: 437 Submissions: 2174 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) 问题描写叙述 今天是BestCoder一周年纪念日. 比赛管理员Soda有一个长度为的字符串. 他想要知道是否能找到的三个互不相交的子串, , 满足下列条件: 1. 2. , , 依次连接之后得到字符串"anniversary". 输

Jetty 9.3庆祝20周年生日快乐,并增加HTTP/2支持

本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2015/06/Building-Distributed-Systems 今年6月12日,Jetty项目发布了旗舰性开源嵌入式应用服务器的9.3版,同时这一天也是该项目的20周年纪念日.此次发布的主要特性包括增加了对HTTP/2服务端(与客户端)支持.系统最低要求Java 8,以及更多的NIO集成与完全重构的调度器.此外,该版本还移除了SPDY网络支持.并修复了自Jetty 9.2.x

比特元携手信息安全工程学院,庆祝抗战胜利70周年,红歌会!

<红歌会> 一.活动主题传承红军之光,奏响青春乐章 二.活动背景   2015年8月15日是我国抗战胜利70周年纪念日,作为当代大学生,我们应该铭记革命的不易,珍惜现在的生活.在激发我院学生热爱祖国.热爱社会主义,乐观开朗.积极向上的精神风貌的同时践行社会主义核心价值观,实现中华民族伟大复兴的远大抱负,展现同学们积极健康的审美追求. 三.活动内容每班组织一个合唱队,齐唱爱国歌曲,进行合唱比赛,决出优胜者,活动中还有丰富的爱国知识竞答,增加大家的爱国主义情怀. 四.活动目的和意义唱响爱国主义歌曲

Jetty 9.3庆祝20周年生日快乐,并添加HTTP/2支持

本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2015/06/Building-Distributed-Systems 今年6月12日.Jetty项目公布了旗舰性开源嵌入式应用server的9.3版,同一时候这一天也是该项目的20周年纪念日.此次公布的主要特性包含添加了对HTTP/2服务端(与client)支持.系统最低要求Java 8.以及很多其它的NIO集成与全然重构的调度器. 此外.该版本号还移除了SPDY网络支持.并修复了