标签:
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