ACM学习之路___HDU 5723(kruskal + dfs)

Abandoned country

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 4487    Accepted Submission(s): 1131

Problem Description
    An abandoned country has n(n≤100000) villages which are numbered from 1 to n. Since abandoned for a long time, the roads need to be re-built. There are m(m≤1000000) roads to be re-built, the length of each road is wi(wi≤1000000). Guaranteed that any two wi are different. The roads made all the villages connected directly or indirectly before destroyed. Every road will cost the same value of its length to rebuild. The king wants to use the minimum cost to make all the villages connected with each other directly or indirectly. After the roads are re-built, the king asks a men as messenger. The king will select any two different points as starting point or the destination with the same probability. Now the king asks you to tell him the minimum cost and the minimum expectations length the messenger will walk.

Input
    The first line contains an integer T(T≤10) which indicates the number of test cases. 

    For each test case, the first line contains two integers n,m indicate the number of villages and the number of roads to be re-built. Next m lines, each line have three number i,j,wi, the length of a road connecting the village i and the village j is wi.

Output
    output the minimum cost and minimum Expectations with two decimal places. They separated by a space.

Sample Input
1
4 6
1 2 1
2 3 2
3 4 3
4 1 4
1 3 5
2 4 6

Sample Output
6 3.33

Problem Description

题意 :

  国家有M条废弃的路和N个点,现在要重新修,求出连通每一个点需要的最短路径是多少,并求在连通的路任意选两个点走,它的最小期望。

解法:

  最短路径好求,单纯最小生成树。但是第一眼看见求期望,MD,啥几把题,很难懂,这都过了这么多天,重新捡起这道题,发现网上都是 最小生成树+dfs 纠结了好久,确实不知道dfs究竟怎么求得期望,看了网上一片博文,大致知道了期望怎么求,但是看懂 dfs 还

是花费了好长时间(看懂之后一直觉得这什么傻逼题)。

具体求每条路的贡献 :

  设某一段路在用DFS遍历路径过程中在该条路径遍历过的次数为 cnt,设该条路length ,则它的贡献就是 cnt * ( nodeNum - cnt ) * length。

  最后题目中所求期望就是所有的路的贡献加起来  除以(nodeNum * ( nodeNum - 1.0 ) / 2.0 ) 。

开始参照网上的代码交了一发 内存有4W K+ , 后来按照以前kruskal 算法的模板(毕竟我还是太水)加上自己一些想法优化些,时间没怎么减少,内存可以降到 2W K+ , 上一发我的代码

  1 #include <bits/stdc++.h>
  2 #define maxn 100005
  3 using namespace std;
  4 double res;
  5
  6 vector< pair<int,int> >Edge1[maxn];
  7
  8 struct Edge
  9 {
 10     int from;
 11     int to;
 12     int length;
 13     friend bool operator < (const Edge &e1 , const Edge &e2)
 14     {
 15         return e1.length > e2.length;//最小值优先
 16     }
 17 };
 18
 19
 20 int father[maxn];    //用来做并查集
 21 int nodeNum,edgeNum;  //顶点数、边数
 22 long long MST;                //最小生成树边权值和
 23
 24 priority_queue<Edge> myQ;   //优先队列
 25
 26 void storeMap()   //存储岛的桥构成的图
 27 {
 28     while(!myQ.empty())
 29         myQ.pop();  //清空队列
 30     int  from,to,length;
 31     for(int i = 0 ; i < edgeNum ; i++)    //kruskal算法对于无向图也只需建一条边即可
 32     {
 33         scanf("%d%d%d",&from,&to,&length);
 34         Edge e;
 35         e.from = from;
 36         e.to = to;
 37         e.length = length;
 38         myQ.push(e);
 39     }
 40 }
 41
 42
 43 int findx(int x)  //查找父节点
 44 {
 45     if(x == father[x])
 46         return father[x];
 47     return father[x] = findx(father[x]);
 48 }
 49
 50
 51 bool judge()   //判断是否是一棵最小生成树 ,这里得注意起点和终点
 52 {
 53     int f = findx(1);
 54     for(int i = 2 ; i <= nodeNum ; i++)
 55     {
 56         if(f != findx(i))
 57             return false;
 58     }
 59     return true;
 60 }
 61
 62
 63 void init()//初始化函数
 64 {
 65     for(int i = 0 ; i <= nodeNum ; i++)
 66     {
 67         father[i] = i;
 68         Edge1[i].clear();
 69     }
 70 return;
 71 }//特意把 maxn 改成 nodeNum 并且把这个模块从底下的函数中独立出来,没想到时间一点也没少,反倒增加了,很是迷茫
 72
 73
 74 int kruskal()   //kruskal算法
 75 {
 76     MST = 0;
 77     int  num = 0;   //记录MST的边数
 78     while(!myQ.empty()  &&  num != nodeNum-1)
 79     {
 80         Edge e = myQ.top();
 81         myQ.pop();
 82         int fx = findx(e.from);
 83         int fy = findx(e.to);
 84         if(fx != fy)
 85         {
 86             father[fx] = fy;
 87             MST += e.length;
 91             Edge1[ e.from ].push_back(make_pair(e.to   , e.length));
 92             Edge1[ e.to   ].push_back(make_pair(e.from , e.length));
 93             num++;
 94         }
 95     }
 96     return num;
 97 }
 98
 99
100 int dfs(int x , int f)
101 {
102     int cnt = 0;//该条路遍历过次数
103     for(int i = 0 ; i < Edge1[x].size() ; i++)
104     {
105         int v = Edge1[x][i].first;
106         if(v == f)
107             continue;
108         int fcnt = dfs( v , x );
109         cnt += fcnt;
110         res = res + 1.0 * fcnt * ( nodeNum - fcnt) * Edge1[x][i].second;//该条路的贡献
111     }
112     return cnt + 1;
113 }
114
115 int main()
116 {
117     //freopen("sample.in" , "r" , stdin);
118     //freopen("sample1.out" , "w" , stdout);
119     int t;
120     scanf("%d",&t);
121     while(t--)
122     {
123         res = 0;
124         scanf("%d%d",&nodeNum , &edgeNum);
125         storeMap();
126         init();
127         kruskal();
128         dfs(1 , 0);
129         res = res * 2.0 / (nodeNum *1.0) /(nodeNum - 1.0);
130         printf("%I64d %.2lf\n",MST,res );
131     }
132     return 0;
133 }
时间: 2024-10-29 19:10:14

ACM学习之路___HDU 5723(kruskal + dfs)的相关文章

ACM学习之路___HDU 1385(带路径保存的 Floyd)

Description These are N cities in Spring country. Between each pair of cities there may be one transportation track or none. Now there is some cargo that should be delivered from one city to another. The transportation fee consists of two parts: The

ACM学习历程—HDU1716 排列2(dfs &amp;&amp; set容器)

Description Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. Input 每组数据占一行,代表四张卡片上的数字(0<=数字<=9),如果四张卡片都是0,则输入结束. Output 对每组卡片按从小到大的顺序输出所有能由这四张卡片组成的4位数,千位数字相同的在同一行,同一行中每个四位数间用空格分隔. 每组输出数据间空一行,最后一组数据后面没有空行. Sample Input 1 2 3 4 1 1 2 3 0 1

ACM学习之路————一个大整数与一个小整数不得不说得的秘密

这个相对于两个大整数的运算来说,只能说是,low爆了. 只要利用好除法的性质,这类题便迎刃而解.O(∩_∩)O哈哈~ //大整数除一个int数 #include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[1000],result[1000]; int main() { long long divis; int n,i,k,flag,len; char c; while

ACM 学习心得

ACM 学习心得 STL:完美的艺术品 STL 由四大部分组成:算法.容器.迭代器.仿函数. 算法(algorithm) 算法定义了一组与实现无关的操作,也是 ACM 学习的核心.C++ 算法库的内容全都是一些比较基本的算法,包括移动.转换.遍历.删除.过滤等等.C++ 算法库本身是基于抽象的,在迭代器的抽象下,使得这些算法可以在不同结构的容器中重用.一个比较坑的地方就是我高中的时候学完 C++ 之后报名了 NOIP.那一年刚刚允许用 STL(之前一直不准用),然后我对于标准库的依赖很严重,连快

我的算法学习之路

关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口--况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门--当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾--反正最后考试划个重点也能过,于是这门整个计算机专业本

Peng Gong:我的算法学习之路

原文出处: Lucida (@peng_gong) 关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口--况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门--当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾--

acm学习报告

前言: "紧张刺激"的大一下学期马上就要结束了!从最初接触C++到现在也已经快要有1年的时间了.在大一上学期,c++课上学的基础知识大部分都是属于c语言的,为了熟练掌握这些基础知识,费老让我们做了很多的练习题.其实,我觉得,这些练习题也可以算是acm的范畴,只不过这些题实在是简单到不能再简单了.到了这一学期,或是说在寒假里,我才真正的知道了ACM题是有多么的困难!!说实话,在上学期做题做的挺轻松地,那是也觉得acm再难还能难倒那里去,于是我就跟随着远飞的脚步,没有犹豫的选修了ACM程序

转----我的算法学习之路

我的算法学习之路 关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口——况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 原文链接:http://zh.lucida.me/blog/on-learning-algorithms/ 原文作者:Lucida 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程

一位Google程序员的算法学习之路(转)

关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口——况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门——当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾——反正最后考试划个重点也能过,于是这门整个计算机专业本