2016 Multi-University Training Contest 1 1001.Abandoned country

来源:互联网 发布:男生衣服品牌 知乎 编辑:程序博客网 时间:2024/05/22 18:48

题目地址:点击打开链接

题目大意:有n个城市要修路,最后希望它们互相直接或间接联通,给了m条备选的路,问最小费用是多少还有就是路长的期望是多少。

解题思路:这题其实和省赛中的挺像,本质就是求最小生成树,对于后面的期望,每一条边的期望等于边两端的点的数量的积乘上边的长度,sigma求和在除以从n个点中取2个点建边的情况即可。

队友的图论水平是越来越高了,直接排序的最小生成树+并查集(果然我还是太弱了),随便令一个作为顶点,在将点数延边传递。

代码:

#include<iostream>#include<vector>#include<cmath>#include<algorithm>#include<ctime>#include "cstdio"#include "string"#include "string.h"using namespace std;const int maxn = 1e5 + 50;struct Edge {int from, to;long long cost;bool operator<(const Edge&rhs)const {return cost < rhs.cost;}}edges[maxn*10],cs[maxn*10];vector<int>G[maxn];int n, m, cnt, fa[maxn], node[maxn];void init(){for (int i = 1;i <= n;i++){G[i].clear();fa[i] = i;}}int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}int dfs(int now, int parent){int siz = G[now].size();int ans = 1;for (int i = 0;i < siz;i++){int next = G[now][i];if (next != parent)ans += dfs(next, now);}node[now] = ans;return ans;}int main(){int T;scanf("%d",&T);while (T--){scanf("%d %d", &n, &m);init();for (int i = 0;i < m;i++)scanf("%d %d %d", &edges[i].from, &edges[i].to, &edges[i].cost);sort(edges, edges + m);long long sum = 0;cnt = 0;memset(node, 0, sizeof(node));for (int i = 0;i < m;i++){int x = edges[i].from;int y = edges[i].to;int dx = find(x);int dy = find(y);if (dx != dy){fa[dx] = dy;sum += edges[i].cost;G[x].push_back(y);G[y].push_back(x);cs[cnt++] = edges[i];}}dfs(1, -1);double exp = 0;for (int i = 0;i < cnt;i++){int x = cs[i].from;int y = cs[i].to;int dMin = min(node[x], node[y]);int dMax = n - dMin;exp += (long long)dMin*dMax*cs[i].cost;}exp = exp / n / (n - 1) * 2;printf("%lld %.2lf\n", sum, exp);}return 0;}



0 0
原创粉丝点击