zoukankan      html  css  js  c++  java
  • 开学测试2018.9.1周年纪念日 BSOJ

    描述
    20180901105217_44309
    输入
    20180901105240_82789
    输出
    20180901105258_73744
    样例输入[复制]
    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
    样例输出[复制]
    11 5
    5 29
     
     
     
    第一个问题显然是最小生成树,直接上板子就可以了
    第二个问题稍微要复杂一点
    首先他是要求一个最小值,我们再来看数据范围发现非常大,n是1e6,如果直接进行暴力的后果是不可想象的
    我们推算一下只有n与nlogn可以符合要求
    但是nlogn不行因为这道题没有二的性质(如果你非说是二分我也没话可说)
    所以只能是线性复杂度
    那么这个复杂度我们分析出来了,发现每个点要O(1)递推
    自然而然我们想到一个递推的方法
     

    观察这个图,显然我们只能一个一个往下递推

    对于x的总值h[x]我们已经算了出来

    如果现在把重心放在了y会产生什么后果?

    对于y及其子树的所有人就会少走d的距离,代价少了d*siz[y]

    记所有人数为all,对于除y以外的人,要多走d,代价多了d*(all-siz[y])

    就这样我们就实现了O(1)递推

    至于那个最开始的值,我们以1为根,进行一次dfs,记录一下每个点到根节点的距离和每个点子树的大小

    然后出来就暴力计算h[1]的值

    最后比较一下就可以了

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define N 1000006
     5 using namespace std;
     6 long long max0=0,ans=0,fa[N],n,m,p[N],min0=999999999999999999999;
     7 long long cnt,first[N],nxt[N],siz[N],dep[N],h[N],temp,all=0;
     8 struct node{
     9     long long u,v,w;
    10 }e[N],g[N];
    11 long long find(long long x){
    12     if(x!=fa[x])return fa[x]=find(fa[x]);
    13     return fa[x];
    14 }
    15 void merge(long long x,long long y){
    16     long long f1=find(x),f2=find(y);
    17     if(f1!=f2){
    18         fa[f1]=f2;
    19     }
    20 }
    21 void add(long long u,long long v,long long w){
    22     e[++cnt].u=u;
    23     e[cnt].v=v;
    24     e[cnt].w=w;
    25     nxt[cnt]=first[u];
    26     first[u]=cnt;
    27 }
    28 void kruskal(){
    29     long long tot=0;
    30     for(long long i=1;i<=m;i++){
    31         long long u=g[i].u,v=g[i].v;
    32         if(find(u)!=find(v)){
    33             merge(u,v);
    34             add(u,v,g[i].w);
    35             add(v,u,g[i].w);
    36             tot++;
    37             ans+=g[i].w;
    38             max0=max(max0,g[i].w);
    39             if(tot==n-1)return;
    40         }
    41     }
    42 }
    43 bool cmp(node a,node b){
    44     return a.w<b.w;
    45 }
    46 void dfs(long long x,long long father){
    47     siz[x]=p[x];
    48     for(long long i=first[x];i;i=nxt[i]){
    49         long long v=e[i].v;
    50         if(v==father)continue;
    51         dep[v]=dep[x]+e[i].w;
    52         dfs(v,x);
    53         siz[x]+=siz[v];
    54     }
    55 }
    56 void dfs2(long long x,long long father){
    57     if(h[x]<min0){
    58         min0=h[x];
    59         temp=x;
    60     }
    61     for(long long i=first[x];i;i=nxt[i]){
    62         long long v=e[i].v;
    63         if(v==father)continue;
    64         h[v]=h[x]-siz[v]*e[i].w+(all-siz[v])*e[i].w;
    65         dfs2(v,x);
    66     }
    67 }
    68 int main(){
    69 //    freopen("anniversary.in","r",stdin);
    70 //    freopen("anniversary.out","w",stdout);
    71     scanf("%lld%lld",&n,&m);
    72     for(long long i=1;i<=n;i++){
    73         fa[i]=i;
    74         scanf("%lld",&p[i]);
    75         all+=p[i];
    76     }
    77     for(long long i=1;i<=m;i++)scanf("%lld%lld%lld",&g[i].u,&g[i].v,&g[i].w);
    78     sort(g+1,g+m+1,cmp);
    79     kruskal();
    80     cout<<ans<<" "<<max0<<endl;
    81     dep[1]=0;
    82     dfs(1,0);
    83     for(long long i=1;i<=n;i++)
    84         h[1]+=dep[i]*p[i];//计算1的总值可以往下递推 
    85     dfs2(1,0);
    86     cout<<temp<<" "<<min0;
    87     return 0;
    88 }

    注意那个极大值要开的非常大非常大

    over,还是很简单的题目,30分钟足矣

  • 相关阅读:
    Opencv保存摄像头视频&&各种编码器下视频文件占用空间对比
    生活的 tricks
    生活的 tricks
    词汇的积累 —— 反义词、同义词
    词汇的积累 —— 反义词、同义词
    目标跟踪系列十一:Exploiting the Circulant Structure of Tracking-by-detection with Kernels代码思路
    Java中Integer类的方法
    php中 重载(二)
    协方差的意义
    malloc函数具体解释
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9570824.html
Copyright © 2011-2022 走看看