您的位置:首页 > 其它

多校2016&&HDU.5723 Abandoned country

2016-07-19 19:48 239 查看
【题意】给了一个图,求最小生成树,然后在n个点任意选两个点。问在这Cn2中选择中,每种选择的两个点的距离的和和Cn2的比值就是期望值!实际上对于每条边就是边权*左子树的大小*右子树的大小的和!今天队友写的这个题,贴他的代码!

【AC代码】

#include<bits/stdc++.h>
using namespace std;
const int N =3e6;
#define LL long long
int head
,num,cnt,sz
,flag
;
double ans;
struct node
{
int st,ed,len;
}E[3*N];
struct node1
{
int nxt,ed,len;
}EE[3*N];
void adde(int x,int y,int d)
{
EE[cnt].ed=y;
EE[cnt].len=d;
EE[cnt].nxt=head[x];
head[x]=cnt++;
}
void add(int x,int y,int d)
{
E[num].st=x;
E[num].ed=y;
E[num++].len=d;
}
bool cmp(node a,node b)
{
return a.len<b.len;
}
int fa
;
int Find(int x)
{
if(fa[x]==x) return x;
return fa[x]=Find(fa[x]);
}
void dfs(int x)
{
sz[x]=1;
for(int i=head[x];~i;i=EE[i].nxt){
int ed=EE[i].ed;
if(sz[ed]==0){
dfs(ed);
sz[x]+=sz[ed];
}
}
}
void init()
{
num=0;
cnt=0;
memset(head,-1,sizeof(head));
memset(sz,0,sizeof(sz));
memset(flag,0,sizeof(flag));
}
void dfs1(int x,int n)
{
flag[x]=1;
for(int i=head[x];~i;i=EE[i].nxt){
int ed=EE[i].ed;
if(!flag[ed]){
ans+=double(EE[i].len)*(n-sz[ed])*(sz[ed]);
dfs1(ed,n);
}
}
}
int main()
{
int T,n,m,x,y,z;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
if(n==1&&m==0){
printf("0 0.00\n");
continue;
}
init();
while(m--){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
sort(E,E+num,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
LL lenn=0;
for(int i=0;i<num;i++){
int st=E[i].st,ed=E[i].ed;
int xx=Find(st),yy=Find(ed);
if(xx!=yy){
lenn+=E[i].len;
fa[xx]=yy;
adde(st,ed,E[i].len);
adde(ed,st,E[i].len);
}
}
//dfs1(1);
dfs(1);
ans=0;
dfs1(1,n);
//printf("%.f\n",ans);
double t=(double)n*(n-1)/2;
ans=ans/t;
printf("%I64d %.2f\n",lenn,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: