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
  • 相关阅读:
    根据navigator.userAgent返回值识别 浏览器
    HTML兼容问题及解决办法
    css 浏览兼容问题及解决办法 (2)
    css 浏览兼容问题及解决办法 (1)
    js 浏览器兼容问题及解决办法
    cookie 笔记
    HTML5基础2
    HTML5基础1
    摩天轮
    造个惊喜盒( ๑ŏ ﹏ ŏ๑ )
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/7717576.html
Copyright © 2011-2022 走看看