• HDU 5723 Abandoned country(最小生成树+边两边点数)


    http://acm.split.hdu.edu.cn/showproblem.php?pid=5723

    题意:
    给出一个无向图,每条路都有一个代价,求出把所有城市连通的最小代价。在此基础上,国王会从这里面随机挑出两个城市作为起点和终点,求出国王要走的路的期望值。

    思路:

    第一问很简单,最小生成树计算一下即可。

    对于第二问,在新图的基础上,考虑每条边所能给出的贡献值。假设这条边两个的点数分别为x和y,那么这条边总的贡献次数就是x*y,贡献值为x*y*w。求两边的点数dfs即可。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<stack>
     7 #include<queue>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef pair<int,int> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const int maxn = 100000 + 5;
    16 
    17 int n, m;
    18 double tot;
    19 
    20 struct node
    21 {
    22     int u,v,w;
    23     bool operator< (const node& rhs) const
    24     {
    25         return w<rhs.w;
    26     }
    27 }edge[1000005];
    28 
    29 int p[maxn];
    30 vector<pll> G[maxn];
    31 
    32 int Find(int x)
    33 {
    34     return p[x]==x?x:p[x]=Find(p[x]);
    35 }
    36 
    37 void Kruskal()
    38 {
    39     ll sum = 0;
    40     int num=0;
    41     sort(edge,edge+m);
    42     for(int i=0;i<m;i++)
    43     {
    44         int x = Find(edge[i].u);
    45         int y = Find(edge[i].v);
    46         if(x!=y)
    47         {
    48             p[x]=y;
    49             sum+=edge[i].w;
    50             num++;
    51             G[edge[i].u].push_back(make_pair(edge[i].v,edge[i].w));
    52             G[edge[i].v].push_back(make_pair(edge[i].u,edge[i].w));
    53         }
    54         if(num==n-1)  break;
    55     }
    56     printf("%I64d ",sum);
    57 }
    58 
    59 
    60 int dfs(int u, int fa)
    61 {
    62     int cnt = 0;
    63     for(int i=0;i<G[u].size();i++)
    64     {
    65         int v = G[u][i].first;
    66         int w = G[u][i].second;
    67         if(v==fa)  continue;
    68         int now = dfs(v, u);
    69         cnt += now;
    70         tot += 1.0 * now * (n - now) * w;
    71     }
    72     return cnt+1;
    73 }
    74 
    75 int main()
    76 {
    77     //freopen("in.txt","r",stdin);
    78     int T;
    79     scanf("%d",&T);
    80     while(T--)
    81     {
    82         scanf("%d%d",&n,&m);
    83         for(int i=0;i<=n;i++)  {p[i]=i;G[i].clear();}
    84         for(int i=0;i<m;i++)
    85         {
    86             scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    87         }
    88         Kruskal();
    89         tot=0;
    90         dfs(1,-1);
    91         printf("%.2f
    ",tot*2.0/(1.0*n)/(n-1.0));
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    洛谷P1600 天天爱跑步——树上差分
    洛谷P1155 双栈排序——思路题
    洛谷P2827 蚯蚓——思路题
    bzoj2763 [JLOI2011]飞行路线——分层图
    洛谷P2831 愤怒的小鸟——贪心?状压DP
    洛谷P1514 引水入城——dfs
    bzoj1854 [Scoi2010]游戏——匈牙利算法
    hdu1814 Peaceful Commission——2-SAT
    浙江理工大学: 铺地砖(3922)
    最大素因子(快)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7648766.html
Copyright © 2020-2023  润新知