2016年暑期多校【1】

1、【HDU 5723】Abandoned country(最小生成树+树形dp)

题意:n(n≤100000)个城市,m(m≤1000000)条路,要修建(n-1)条路使这n个城市连通,题目中告诉我们修建每条路的费用,需要求两个问题:1、修建(n-1)条路的最小费用 2、路修建好了之后,任意两点之间的长度的期望

解题思路:

修建(n-1)条路的最小费用==>最小生成树

路修建好了之后,任意两点之间的长度的期望:实际上就是求任意两点之间的平均距离。对于边X,求所有可能的路径经过此边的次数:设这条边两端的点数分别为A和B, 点A的子树的大小是size(A),设点B的子树大小是size(B),【这里所说的子树都是不经过边X的】那么这条边被经过的次数就是size(A)*size(B),它对总的距离和的贡献就是

(size(A)*size(B)*边X的长度)。求出所有边的贡献总和然后除以(n*(n-1)/2)就是所求值

long long没有处理好,wa了很多次。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <string>
 6 #include <vector>
 7 using namespace std;
 8 #define ll long long
 9 const int N=1e6+10;
10
11 struct node{
12     int u, v, w;
13     friend bool operator < (const node n1, const node n2){
14         return n1.w<n2.w;
15     }
16 }a[2*N];
17
18 struct Node{
19     int v, len;
20     Node(int _v, int _len):v(_v), len(_len){}
21 };
22
23 int fa[N];
24 vector<Node>vec[N];
25 int find(int x)
26 {
27     return fa[x]=(fa[x]==x?x:find(fa[x]));
28 }
29 ll kruskal(int n, int m)
30 {
31     ll ans=0;
32     int tmp=0;
33     for(int i=1; i<=n; i++) fa[i]=i, vec[i].clear();
34     for(int i=0; i<m; i++)
35     {
36         if(tmp>=n-1) break;
37         int ui=find(a[i].u), vi=find(a[i].v);
38         if(ui!=vi)
39         {
40             tmp++, fa[vi]=ui, ans+=(ll)a[i].w;
41             vec[a[i].u].push_back(Node(a[i].v, a[i].w));
42             vec[a[i].v].push_back(Node(a[i].u, a[i].w));
43         }
44     }
45     return ans;
46 }
47
48 ll dis[N];
49 int sum[N];
50 int n;
51 void dfs(int u, int p){
52
53     sum[u]=1;
54     for(int i=0; i<(int)vec[u].size(); i++){
55         int vi = vec[u][i].v;
56         int wi = vec[u][i].len;
57         if(vi==p) continue;
58         dfs(vi, u);
59         sum[u]+=sum[vi];
60         dis[u] += dis[vi]+((ll)sum[vi]*(n-sum[vi]))*wi;
61     }
62
63 }
64
65 int main(){
66     int t;
67     scanf("%d", &t);
68     while(t--){
69         int m, lena=0;
70         scanf("%d%d", &n, &m);
71         int ui, vi, wi;
72         for(int i=0; i<m; i++){
73             scanf("%d%d%d", &ui, &vi, &wi);
74             a[lena].u=ui, a[lena].v=vi, a[lena].w=wi, lena++;
75             a[lena].u=vi, a[lena].v=ui, a[lena].w=wi, lena++;
76         }
77         sort(a, a+lena);
78         ll ans = kruskal(n, lena);
79         memset(dis, 0, sizeof(dis));
80         dfs(1, -1);
81         ll s = (ll)n*(n-1)/2;
82         printf("%lld %.2lf\n", ans, dis[1]*1.0/s);
83     }
84     return 0;
85 }

时间: 2025-01-04 03:34:58

2016年暑期多校【1】的相关文章

HDU 5742 It&#39;s All In The Mind (贪心) 2016杭电多校联合第二场

题目:传送门. 题意:求题目中的公式的最大值,且满足题目中的三个条件. 题解:前两个数越大越好. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(int a,int b) { if(!b) return a; return gcd(b,a%b); } int main() { int t; ci

暑期多校 第一场

A: 描述: 代码: 1 #include <iostream> 2 #include <stdio.h> 3 #include <math.h> 4 #include <string.h> 5 using namespace std; 6 7 int k,p; 8 int a[104]; 9 //void solve(){ 10 // int ans=0; 11 // for(int i=1;i<=k;i++){ 12 // ans=0; 13 //

HDU 5793 A Boring Question (费马小定理) ---2016杭电多校联合第六场

A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 156    Accepted Submission(s): 72 Problem Description There are an equation.∑0≤k1,k2,?km≤n∏1?j<m(kj+1kj)%1000000007=?We define t

HDU 5795 A Simple Nim (博弈) ---2016杭电多校联合第六场

A Simple Nim Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 79    Accepted Submission(s): 48 Problem Description Two players take turns picking candies from n heaps,the player who picks the las

HDU 5762 Teacher Bo (鸽笼原理) 2016杭电多校联合第三场

题目:传送门. 题意:平面上有n个点,问是否存在四个点 (A,B,C,D)(A<B,C<D,A≠CorB≠D)使得AB的横纵坐标差的绝对值的和等于CD的横纵坐标差的绝对值的和,n<10^5,点的坐标值m<10^5. 题解:表面上这道题复杂度是O(n^2)会超时的,而实际上这些坐标差绝对值的和最大是2*10^5,所以复杂度不是O(n^2),而是O(min(n^2,m)),这就是著名的鸽笼原理. #include <iostream> #include <cstdio

HDU 5745 La Vie en rose (DP||模拟) 2016杭电多校联合第二场

题目:传送门. 这是一道阅读理解题,正解是DP,实际上模拟就能做.pij+1 指的是 (pij)+1不是 pi(j+1),判断能否交换输出即可. #include <iostream> #include <algorithm> #include <cstdio> #include<cstring> using namespace std; int t,n; char str1[100009],str2[5009]; char tmp[5009]; int m

HDU 5734 Acperience (公式推导) 2016杭电多校联合第二场

题目:传送门. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(long long a,long long b) { if(!b) return a; return gcd(b,a%b); } int a[100005]; int main() { int T,n; scanf("%d

HDU 5752 Sqrt Bo (思维题) 2016杭电多校联合第三场

题目:传送门. 题意:一个很大的数n,最多开5次根号,问开几次根号可以得到1,如果5次还不能得到1就输出TAT. 题解:打表题,x1=1,x2=(x1+1)*(x1+1)-1,以此类推.x5是不超过long long的,判断输出即可. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long

HDU 5744 Keep On Movin (贪心) 2016杭电多校联合第二场

题目:传送门. 如果每个字符出现次数都是偶数, 那么答案显然就是所有数的和. 对于奇数部分, 显然需要把其他字符均匀分配给这写奇数字符. 随便计算下就好了. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int main() { int T,n,a; scanf("%d",&T);