码迷,mamicode.com
首页 > 其他好文 > 详细

警察叔叔就是这个人!

时间:2017-10-23 18:39:24      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:--   sort   class   iostream   blog   void   clu   ret   ace   

给定一个无向有权图,首先一个最小生成树 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

 

警察叔叔就是这个人!

标签:--   sort   class   iostream   blog   void   clu   ret   ace   

原文地址:http://www.cnblogs.com/Kong-Ruo/p/7717576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!