Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3006 Accepted Submission(s): 346
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x7f7f7f7f
#define FOR(i,n) for(int i=1;i<=n;i++)
#define CT continue;
#define PF printf
#define SC scanf
const int mod=1000000007;
const int N=1e6+10;
int num[N],f[N];
vector<int> G[N];
struct edge{
int u,v,cost,flag;
}e[N];
bool cmp(edge a,edge b)
{
return a.cost<b.cost;
}
int findr(int u)
{
if(f[u]!=u)
f[u]=findr(f[u]);
return f[u];
}
int dfs_clock;
void dfs(int u,int pre)
{
int p=++dfs_clock;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==pre) continue;
dfs(v,u);
}
num[u]=dfs_clock-p+1;
}
int main()
{
int cas,n,m;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].cost);
e[i].flag=0;
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++) f[i]=i;
ll cost=0;
for(int i=1;i<=m;i++)
{
int u=findr(e[i].u),v=findr(e[i].v);
if(u==v) continue;
f[u]=v;
e[i].flag=1;
cost+=e[i].cost;
G[e[i].u].push_back(e[i].v);
G[e[i].v].push_back(e[i].u);
}
dfs_clock=0;
dfs(1,-1);
double q=0;
for(int i=1;i<=m;i++)
if(e[i].flag)
{
int u=e[i].u,v=e[i].v;
ll k=min(num[u],num[v]);
q+=k*(n-k)*e[i].cost;
}
q=2*q/n/(n-1);
printf("%lld %.2f\n",cost,q);
}
return 0;
}
分析:刚开始以为是道kruskal+统计子节点的水题,,,,后来写了下,,发现这道题目有个很迷的地方,就是连接起所有村庄的最小的总cost和最小的期望值,最小的cost当然跑kruskal,那会不会在同一种
cost的情况下出现不同期望值?那该怎么选择,,,于是瞬间懵逼,,就放弃了。。。
可见,,比赛时缺乏基本的随机应变和见招拆招的能力,,这要靠比赛来加强了。。。。比赛时胆子真的太小了,,,只有多多比赛慢慢克服了。。。
解决:其实因为题目说了所有边的权值均不同,,kruskal中对边sort后,形成最小生成树的边的选取方案是
唯一的,所以最小生成树唯一;
hdu 5723 Abandoned country 最小生成树+子节点统计
原文:http://www.cnblogs.com/smilesundream/p/5738581.html