• 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
    ",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
    ",pos,ans);
    117     return 0;
    118 }
    119 
    120 int sb=hh();
    121 int main(int argc,char**argv) {;}
    代码


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    AccessControlAllowOrigin 跨域设置多域名
    C#基于LibUsbDotNet实现USB通信(一)
    移动端设置行高等于高度的时候文本不居中???
    阿里云OSS设置跨域访问还是不行。
    没错,就是AccessControlAllowOrigin,跨域
    移动端 lineheight 文字不居中问题解决方案
    Chromium.org team 改进vs编译速度的一些建议
    isapi x86 在win7x64下的安装问题
    Entity Framwork one to one problem
    Google Talk使用技巧
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7505324.html
Copyright © 2020-2023  润新知