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

【考试】9.5(2)

时间:2019-09-05 23:35:16      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:tor   code   div   特殊   输出   ring   最大   pre   处理   

3>警察叔叔

题面真皮,复制自题解

考点:MST+树的遍历

 

题目大意:

给定一个无向有权图,

首先一个最小生成树 MST,从 MST 中选取一个度数大于 1 的点 作为根 K,

使每颗子树及该子树到根的边权之和方差最小。

输出 K 和最小方差的值。

 

由于N 比较大,所以只能通过 Kruskal 求MST,

接下来任选一个点作为根,进行一次遍历。

记录 w[i]表示以 i 点作为根的子树的边权之和。

 

然后依次枚举每一个点 i,该点的子树权值可以直接求出,

而以它父亲作为根的子树需要特殊处理。

这颗特殊子树的权值为最小生成树总权值减去该点权值 w[i]。

然后计算出方差,最后选取所有点当中最小方差的那个点即可。

时间复杂度:O(MlogM+N)

 

代码也不长,就是小数烦人

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
int n,m;
const int N=40003;
struct node
{
    int v;double w;
    bool operator < (const node & o) const 
    { return w>o.w; }
    node(int vv,double ww)
    { v=vv,w=ww; }
    node(){}
};
vector <node> g[N];

struct nd
{
    int u,v;double w;
    bool operator < (const nd & o) const
    { return w>o.w; }
};
int f[N];
int find(int x)
{ return !f[x]?x:f[x]=find(f[x]); }
void MST()
{
    priority_queue <nd> q;    
    scanf("%d%d",&n,&m);
    nd t;
    while(m--)
    {
        scanf("%d%d%lf",&t.u ,&t.v ,&t.w );
        q.push(t); 
    }
    int cnt=1;
    while(!q.empty() && cnt<n)
    {
        t=q.top() ;q.pop() ;
        int fu=find(t.u ),fv=find(t.v );
        if(fu==fv) continue;
        
        f[fu]=fv,cnt++;
        g[t.u ].push_back(node(t.v ,t.w )); 
        g[t.v ].push_back(node(t.u ,t.w )); 
    }
}
int fa[N],g_sz[N];
double son[N],gg[N];
void dfs(int nw,int pre)
{
    fa[nw]=pre;
    g_sz[nw]=g[nw].size() ;
    for(int i=0;i<g_sz[nw];i++)
    {
        int v=g[nw][i].v ;
        if(v==pre) continue;
        dfs(v,nw);
        son[nw]+=son[v]+g[nw][i].w ;
    }
}

int main()
{
    MST();
    dfs(1,0);
    double ans=-1;int pos=0;
    for(int i=1;i<=n;i++)
    {
        if(g_sz[i]==1) continue;
        
        double ave=son[1]/g_sz[i];
        double check=0;
        for(int j=0;j<g_sz[i];j++)
        {
            int v=g[i][j].v ;
            double t;
            if(v==fa[i])
                t=son[1]-son[i];
            else
                t=son[v]+g[i][j].w ;
            t-=ave;
            check+=t*t;
        }
        if(ans==-1 || check<ans) ans=check,pos=i;
    }
    printf("%d",pos);
    
    return 0;
}

记住这里的ans,

如果不知道什么是最大值,就不要瞎设,1e18都过不了。

不如老老实实-1

【考试】9.5(2)

标签:tor   code   div   特殊   输出   ring   最大   pre   处理   

原文地址:https://www.cnblogs.com/xwww666666/p/11470343.html

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