zoukankan      html  css  js  c++  java
  • 宿命的P.S.S

    题目描述

    1.背景描述Background
    P.S.S:“我来自哪里?”
    WH:“你来自一个图。”
    P.S.S:“我是谁?”
    WH:“你是最小生成树。”
    P.S.S:“我又要到哪里去?”
    WH:“你要成为一个最小完全图(边权之和最小的完全图)。”
    P.S.S:“为……为什么啊?”
    WH:“这是你的宿命!因为你无聊!!!P.S.S!”
    2.问题描述Description
    最小生成树P.S.S在宿命的指引下找到了巫师Kismi。P.S.S希望Kismi能帮自己变成一个完全图。Kismi由于某些不可告人的原因,把这件事交给了你。
    PS: 可以保证,这个最小生成树对于最后求出的完全图是唯一的。
    7.时间限制Time Limitation
    每个测试点1s。
    8.数据规模:
    Test1-Test10 n<60
    Test11-Test25 n<20000
    注释Hint: 
    对于样例1,我们只需在1-3间加入一条边权为8的边即可得到最小完全图。其权和是4+7+8=19。对于样例2,我们在2-3间加入一条边权为2的边,在2-4和3-4间加入边权为3的边即可得到最小完全图,其权和是:1+1+2+2+3+3=12。
    感谢吴豪牛对比赛的支持!!!

    输入格式

    输入的第一行是一个整数n,表示生成树的节点数。
    接下来有n-1行,每行有三个正整数,依次表示每条边的端点编号和边权。
    (顶点的边号在1-n之间,边权<maxint)

    输出格式

    一个整数ans,表示以该树为最小生成树的最小完全图的边权之和。

    本题乃逆向思维的经典题目啊。

    首先O(n^2)的算法肯定是不能过的。

    用kruskal算法的逆算法。

    经典 经典

     1 #include<iostream>
     2 #include<fstream>
     3 #define fin cin
     4 using namespace std;
     5 //ifstream fin("cin.in");
     6 
     7 long long n,ans=0;
     8 long long f[20005],tot[20005];
     9 struct{long long u,v,w;}edg[20005];
    10 
    11 void Quick(long long l,long long r){
    12      if(l>=r) return ;
    13      long long i=l,j=r,mid=edg[(l+r)>>1].w;
    14      while(i<=j)
    15      {
    16        while(edg[i].w<mid) i++;
    17        while(edg[j].w>mid) j--;
    18        if(i<=j)
    19        {
    20          swap(edg[i].u,edg[j].u);
    21          swap(edg[i].v,edg[j].v);
    22          swap(edg[i].w,edg[j].w);
    23          i++;j--;
    24                }   
    25                 }
    26      Quick(l,j);
    27      Quick(i,r);
    28      }
    29 
    30 long long Find(long long v){
    31      if(f[v]==v) return v;
    32      f[v]=Find(f[v]);
    33      return f[v];
    34      }
    35 
    36 int main()
    37 {
    38     fin>>n;
    39     
    40     for(long long i=1;i<n;++i)
    41     fin>>edg[i].u>>edg[i].v>>edg[i].w;
    42     for(long long i=1;i<=n;++i)
    43     f[i]=i,tot[i]=1;
    44     
    45     Quick(1,n-1);
    46     
    47     for(long long i=1;i<n;++i)
    48     {
    49       long long fy=Find(edg[i].u);
    50       long long fx=Find(edg[i].v);
    51       ans+=edg[i].w+(tot[fy]*tot[fx]-1)*(edg[i].w+1);
    52       f[fx]=fy;
    53       tot[fy]+=tot[fx];
    54              }
    55     cout<<ans<<endl;
    56    // system("pause");
    57     return 0;
    58     
    59     } 
  • 相关阅读:
    自定义瀑布流
    传值 属性 block 单例 协议
    sqlite数据库中 保存和读取UIData对象
    SQL
    关于在Xcode控制台打印的注意点
    synthesize的作用
    iPhone屏幕尺寸/launch尺寸/icon尺寸
    关于TableView上有一段留白的解决方法
    mac显示隐藏文件
    多线程之GCD
  • 原文地址:https://www.cnblogs.com/noip/p/2708859.html
Copyright © 2011-2022 走看看