最小生成树 kruskal hdu 5723 Abandoned country

题目链接:hdu 5723 Abandoned country

题目大意:N个点,M条边;先构成一棵最小生成树,然后这个最小生成树上求任意两点之间的路径长度和,并求期望

/**************************************************************
    Problem:hdu 5723
    User: youmi
    Language: C++
    Result: Accepted
    Time:2932MS
    Memory:22396K
    solution:首先注意到任意两条边的边权是不一样的,由此得知最小生成树是唯一的,最小生成树既然是唯一的,             那么期望其实也就是唯一的,不存在什么最小期望。求完最小生成树之后,接下来的问题就可以转换成             在最小生成树上求任意两点之间距离的平均值,对于每条边,统计所 有的路径用到此边的次数,也就             是边的两端的点数之积。那么这条边的总贡献就是次数*边 权。最后得到所有边的贡献之和再除以总路             径数n*(n-1)/2n∗(n−1)/2就是答案。可以OnOn求出。任取一点为根dfs,对每个点ii记录其子树包             含的点数(包括其自身),设点数为sum[i]sum[i],则ii的父亲一侧的点数即为n-sum[i]n−sum[i]。             一边遍历一边统计就行。
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
    char c; int flag = 1;
    for (c = getchar(); !(c >= ‘0‘ && c <= ‘9‘ || c == ‘-‘); c = getchar()); if (c == ‘-‘) flag = -1, n = 0; else n = c - ‘0‘;
    for (c = getchar(); c >= ‘0‘ && c <= ‘9‘; c = getchar()) n = n * 10 + c - ‘0‘; n *= flag;
}
int Pow(int base, ll n, int mo)
{
    if (n == 0) return 1;
    if (n == 1) return base % mo;
    int tmp = Pow(base, n >> 1, mo);
    tmp = (ll)tmp * tmp % mo;
    if (n & 1) tmp = (ll)tmp * base % mo;
    return tmp;
}
//***************************

int n,m;
const int maxn=200000+10;
int T,head[maxn],fa[maxn],vis[maxn];
struct Edge
{
    int u,v;
    ll w;
    void init(int _u,int _v,ll _w)
    {
        u=_u,v=_v,w=_w;
    }
}edge[maxn*10];
int get_f(int u)
{
    return u==fa[u]?u:fa[u]=get_f(fa[u]);
}
bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}
struct side
{
    int v,next;
    ll w;
}e[maxn*10];
void init()
{
    T=0;
    ones(head);
    zeros(vis);
}
void build(int u,int v,ll w)
{
    e[T].v=v;
    e[T].w=w;
    e[T].next=head[u];
    head[u]=T++;
}
void kruskal()
{
    sort(edge+1,edge+1+m,cmp);
    rep(i,0,n)
        fa[i]=i;
    ll sum=0;
    rep(i,1,m)
    {
        int f1=get_f(edge[i].u);
        int f2=get_f(edge[i].v);
        if(f1!=f2)
        {
            fa[f2]=f1;
            build(edge[i].u,edge[i].v,edge[i].w);
            build(edge[i].v,edge[i].u,edge[i].w);
            sum+=edge[i].w;
            //j++;
        }
    }
    printf("%I64d ",sum);
}
double tt;
ll dfs(int u)
{
    ll num=1,temp=0;
    vis[u]=1;
    for(int i=head[u];~i;i=e[i].next)
    {
        int v=e[i].v;
        ll w=e[i].w;
        if(!vis[v])
        {
            temp=dfs(v);
            tt+=1.0*w*(1.0*(n-temp)*temp);
            num+=temp;
        }
    }
    return num;
}

void sovle()
{
    tt=0;
    dfs(1);
    tt=tt*2.0/(1.0*n*(n-1));
    printf("%.2lf\n",tt);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        sc(n);
        sc(m);
        init();
        int u,v;
        ll w;
        rep(i,1,m)
        {
            sc2(u,v);sclld(w);
            edge[i].init(u,v,w);
        }
        kruskal();
        sovle();
    }
}
时间: 2024-10-17 06:11:42

最小生成树 kruskal hdu 5723 Abandoned country的相关文章

HDU 5723 Abandoned country 最小生成树+搜索

Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 4477    Accepted Submission(s): 1124 Problem Description An abandoned country has n(n≤100000) villages which are numbered from 1

hdu 5723 Abandoned country(最小生成树,dfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5723 Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2969    Accepted Submission(s): 725 Problem Description An abandoned country

hdu 5723 Abandoned country 最小生成树+子节点统计

Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3006    Accepted Submission(s): 346 Problem Description An abandoned country has n(n≤100000) villages which are numbered from 1

HDU 5723 Abandoned country

题目说每条边权值都不一样,说明最小生成树是唯一的,不存在最小期望这一说. 然后就是先求出最小生成树,随便确定一个根节点,计算出每个点的子树有多少节点,记为c[x]. 指向x的这条边被统计的次数为c[x]*(n-c[x]).然后基本就可以算出答案了. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<

HDU5723 Abandoned country 最小生成树+深搜回溯法

Description An abandoned country has n(n≤100000) villages which are numbered from 1 to n. Since abandoned for a long time, the roads need to be re-built. There are m(m≤1000000) roads to be re-built, the length of each road is wi(wi≤1000000). Guarante

SOJ4339 Driving Range 最小生成树 kruskal算法

典型的最小生成树 然后求最大的一条边 附上链接 http://cstest.scu.edu.cn/soj/problem.action?id=4339 需要注意的是有可能有 "IMPOSSIBLE" 的情况 这里用一个flag标记 记录所并的节点 只有flag = n时才能成功 负责就 "IMPOSSIBLE" 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring&g

ZOJ 3204 Connect them (C) 最小生成树kruskal

Connect them Time Limit: 1 Second      Memory Limit: 32768 KB You have n computers numbered from 1 to n and you want to connect them to make a small local area network (LAN). All connections are two-way (that is connecting computers i and j is the sa

HDU2988 Dark roads 【最小生成树Kruskal】

Dark roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 583    Accepted Submission(s): 253 Problem Description Economic times these days are tough, even in Byteland. To reduce the operating

最小生成树 kruskal算法简介

生成树--在一个图中的一个联通子图  使得所有的节点都被(访问) 最小生成树 (MST) 即联通子图的总代价(路程)最小 已知的一个图 有n个点 m条边 kruskal的算法如下 先对边从小到大排序 从最小的边起,不停的合并这条边的两个节点到一个集合,如果这条边的两个节点已经在一个集合里,则无视,否则形成回路(显然错误)直到所有的节点并到一个集合里 这里需要用到并查集来合并节点 1 int cmp(const int i,const int j) { 2 return w[i] < w[j];