zoukankan      html  css  js  c++  java
  • *叔叔就是这个人!

    给定一个无向有权图,首先一个最小生成树 MST,从 MST 中选取一个度数大于 1 的点 作为根 K,使每颗子树及该子树到根的边权之和方差最小。输出 K 和最小方差的值。

    对于60%的数据:3 ≤ N ≤ 2,000,N-1 ≤ M ≤ 50,000

    对于100%的数据:3 ≤ N ≤ 40,000,N-1 ≤ M ≤ 200,000

    对于100%的数据:0 < len ≤ 100,000,000

    首先肯定要搞MST。。。数据大所以kruska

    然后dfs把MST搞成一个有根树

    有根树上记每个点记以它为根的子树权值和

    枚举每一个点,和它连通的部分就是它的每一个子树和整棵树除了它所在的子树以外的各个部分

    算一下方差就OJBK

    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    const int INF=2147493233;
    using namespace std;
    int n,m;
    struct edge
    {
        int from,to;
        double v;
        bool operator<(const edge &b)const
        {
            return v<b.v;
        }
    }edg[439677];
    int ans,cnt;
    int fa[439600];
    inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    bool same(int x,int y){return find(x)==find(y);}
    void link(int x,int y){fa[find(x)]=find(y);}
    int first[80010],to[80010],next[80010];
    double val[80010];
    bool tag[40010];
    double dp[40010];
    bool vis[40010];
    int master[40010];
    int rank[40010];
    inline void add(int u,int v,double w)
    {
        to[++cnt]=v;
        next[cnt]=first[u];
        first[u]=cnt;
        val[cnt]=w;
        
        to[++cnt]=u;
        next[cnt]=first[v];
        first[v]=cnt;
        val[cnt]=w;
    }
    void kruskal()
    {
        for(int i=0;i<=439600;i++)fa[i]=i;
        sort(edg+1,edg+m+1);
        for(int i=1;i<=m;i++)
        {
            int u=find(edg[i].from),v=find(edg[i].to);
            if(u!=v)
            {
                fa[u]=v;
                add(edg[i].from,edg[i].to,edg[i].v);
            }
        }
    }
    void dfs(int x)
    {
        if(vis[x])return;
        vis[x]=1;
        for(int i=first[x];i;i=next[i])
        {
            if(!vis[to[i]])
            {
                rank[x]++;
                dfs(to[i]);
                master[to[i]]=x;
                dp[x]+=(dp[to[i]]+val[i]);
            }    
        }
    }
    int a,b;
    double c;
    int main()
    {
        double ans=2147483233.0;
        int Ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lf",&a,&b,&c);
            edg[i]=(edge){a,b,c};
        }
        kruskal();
        dfs(1);
        for(int i=n;i>=1;i--)
        {
            int crt=rank[i]+(master[i]!=0);
            if(crt<2)continue;
            double sum=0,avg=dp[1]/crt,res=dp[1]-dp[i];
            for(int j=first[i];j;j=next[j])
            {
                if(to[j]!=master[i])sum+=(double)(val[j]+dp[to[j]]-avg)*(val[j]+dp[to[j]]-avg);
                if(i!=1)sum+=(res-avg)*(res-avg);
            }
            if(sum<ans)
            {
                ans=sum;
                Ans=i;
            }
        }
        cout<<Ans;
        return 0;
    }
    View Code
  • 相关阅读:
    php判断token有效期
    ecshop数据库操作
    CSS3选择器 :nth-child(n) 如何理解
    socket_wirte、socket_read、socket_send、socket_recv
    Mysql按指定顺序排序的两种写法
    Photoshop图片优化文件大小
    Wordpress中的自定义栏目是什么玩意,有什么用?
    Windows使用压缩包安装Mysql5.7.17服务
    Discuz论坛搬家后出现 Unknown column 'app1' in 'where clause' 原因及解决办法
    .PHP后缀大写导致Linux下Composer找不到类
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/7717576.html
Copyright © 2011-2022 走看看