【HDU4313】Matrix 多校 解题报告+AC代码+思路+算法正确性证明,此为Kruskal贪心简单版本,恶心版本稍后放出【目标达成 0.2%】
2012-08-02 03:26
507 查看
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> using namespace std; /** c0de4fun声明:本人未给出测试数据、未声明一次AC的题均为参考解题报告自己写的。 对那些无私贡献的大神真诚的致敬!本题的测试数据可以看最后面 Problem: HDU4313 - Matrix Reference: I- http://page.renren.com/601081183/note/862977450?ref=minifeed&sfet=2012&fin=5&ff_id=601081183&feed=page_blog&tagid=862977450&statID=&level= 好吧这个网址太尼玛蛋疼了!如果想看的话,人人网搜索HDOJ 找到2012 Multi-University Training Contest 2 Solution Report 1004-Matrix就是本题的思路。 II- http://www.2cto.com/kf/201207/144028.html ↑参考代码 来源居然是红黑联盟…… 很多年前了吧,现在也洗白了。 祝他们发展的越来越好 Knowledge Point: Kruskal+贪心算法 【或】 树形DP,本版本是Kruskal的,还会写树形dp Version: Kruskal贪心简单版 Thought: 解题思路: 并查集+贪心 思路: 我们把有机器的节点颜色染成黑色(看到这句话别怕。。。其实跟什么红黑树一点关系都没有,就是为了方便) 那么,如果一个集合中有黑色节点的话,他就不能再跟有黑色节点的集合连接,也不能再连接黑色节点。 我们判断代表节点的颜色,然后按照Kruskal生成树,如果碰到集合代表是黑色节点,并且将与黑色节点连接或者 与另一个代表节点为黑色的集合连接,我们就干掉这条边,并且费用增加对应的权值。 一、关于采用Kruskal贪心算法正确性的证明。 【注意,我们这里关于有些术语的定义跟《算法导论》中的不一样!请仔细阅读!】 【注意,我们在使用该贪心算法之前已经将边按照《权值由高到低》排序了,阅读时请务必记住这一点】 前提: 给定的树是一颗。。。那叫什么树啊,也不叫最小生成树,反正就是能让全图连起来的树咯。 定义: 【安全边】:加入该边之后不会使两台机器连起来的边。 1.初始化: 对于第一条加入树的边(i,j),有三种情况: I.color[i]与color[j]都是白色——(i,j)安全边,加入树 II.color[i]与color[j]一黑一白——(i,j)安全边,加入树 III.color[i]与color[j]都是黑色——危险边,删除并计算费用!( sum = sum + weight(i,j) ) 由于我们将边按照权值由高到低排列了,那么无论是以上三种情况的哪一种,sum都是最优的。 2.保持 对于一个安全边集合(就是已经确定了一棵树,但是该树未遍历完所有的边,亦即还有一些边没有加入到树中) ,新加入该集合的边(i,j)与I其实一样的,分1.中的三种情况。 那么,【由于边按照权值从高到低排序】,已经加入这棵树中的所有边都是安全边,我们遇到的要加入这棵树的第一条危险边就是费用最小的、让机器联通起来的边了。 因为权值大的安全边都被我们尽可能的塞进了这棵树。 那么此时费用sum也是最优的。 如果这么说想不明白的话,那么就把这个安全边的集合想象成一个新的节点i,j是即将跟它连起来的节点! 3.终止 这还终止个毛啊,根据1和2遍历完给定图中所有的边之后,我们得到的必然是最小费用,直接输出就好。 二、并查集代表节点颜色问题(这部分在这个代码中没有体现,不给出证明了,在恶心代码中会给出证明) */ const int WHITE = 0; const int BLACK = 1; const int MAX_SIZE = 100010; struct node { int id; int x; int y; int val; }; node nodes[MAX_SIZE]; int fa[MAX_SIZE]; //娘希匹的,以后并查集强迫自己用int数组写,否则写到struct里太非主流 int color[MAX_SIZE]; //节点颜色 int rank[MAX_SIZE]; int comp (const void *a,const void *b) { node *_a = (node*)a; node *_b = (node*)b; return _b->val - _a->val; //sort by val,order by decrease. } int findFather(int id) { int x = id; while ( fa[x] != x ) { fa[x] = fa[ fa[x] ]; x = fa[x]; } //这么写并查集不会超过三层。 return x; } bool join(int x,int y) { int fax = findFather(x); int fay = findFather(y); if( (fax != fay ) && (color[fax] == BLACK && color[fay] == BLACK ) ) { return false; } if( color[fax] == BLACK ) { fa[fay] = fax; rank[fax] = rank[fax] + rank[fay]; } // if( color[fay] == BLACK ) else { fa[fax] = fay; rank[fay] = rank[fay] + rank[fax]; } return true; } long long solve(int N) { long long res = 0; for(int i = 0 ; i < N-1 ;i++) { if ( join(nodes[i].x,nodes[i].y) == 0 ) { //#define DBG #ifdef DBG printf("double black cuted : %d %d val is %d\n",nodes[i].x,nodes[i].y,nodes[i].val); #endif //join faild. Two black node has been linked! deleted. res = res + nodes[i].val; } } return res; } int main() { #ifndef ONLINE_JUDGE freopen("B:\\acm\\SummerVacation\\DP-II\\C.in","r",stdin); freopen("B:\\acm\\SummerVacation\\DP-II\\C.out","w",stdout); #endif int N,K,T; while(scanf("%d",&T) != EOF) { for(int t = 1 ; t <= T; t++) { memset(fa,0,sizeof(fa)); memset(color,0,sizeof(color)); memset(nodes,0,sizeof(nodes));//memset是TLE和MLE杀手,不过据说是初始化大数组最快的,╮(╯_╰)╭谁知道呢 scanf("%d%d",&N,&K); //initallization over. for(int i = 0 ; i < N-1 ; i++) { scanf("%d%d%d",&nodes[i].x,&nodes[i].y,&nodes[i].val); nodes[i].id = i; //fa[i] = i; //Its father is itself. // rank[i] = 1; // color[i] = WHITE; // No machine. fa[nodes[i].x] = nodes[i].x; fa[nodes[i].y] = nodes[i].y; rank[nodes[i].x] = 1; rank[nodes[i].y] = 1; color[nodes[i].x] = WHITE; color[nodes[i].y] = WHITE; } for(int i = 0 ; i < K ; i++) { int nid; scanf("%d",&nid); color[nid] = BLACK; //set it have a machine. } qsort(nodes,N-1,sizeof(nodes[0]),comp); long long ans = solve(N); printf("%I64d\n",ans); } } #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif return 0; }2
5 3
2 1 8
1 0 5
2 4 5
1 3 4
2
4
0
14 4
0 1 1
0 4 4
1 3 3
2 1 2
5 4 5
5 8 7
5 7 8
6 5 6
9 6 1
9 10 9
12 9 10
11 9 11
13 11 12
11
5
3
1
相关文章推荐
- 【HDU4313】Matrix 多校 解题报告+AC代码+思路+算法正确性证明,此为Kruskal贪心恶心版本,非自虐倾向慎入!建议想找解题报告的童鞋看简单版本的,这个我写给自己【目标达成 0.2%】
- 【HDU4313】 - Matrix - 树状DP Version 思路+解题报告+AC代码【0.4%达成】
- 【HDU3415】Max Sum of Max-K-sub-sequence,思路+解题报告+AC代码+自虐般疯狂吐槽【0.3%达成!】
- [Hnoi2010]Matrix 矩阵解题报告及AC代码
- 简单典型贪心---(解题报告)HDU2037---今年暑假不AC
- 【HDU2780 - Su-Su-Sudoku】 解题报告+思路+代码,差点一次AC T^T
- 【ZOJ3471】Most Powerful, 思路+源代码+解题报告(好久没写解题报告了……)【目标达成:0.1%】
- 【HDU1686】Oulipo 思路+解题报告+代码+KMP算法个人理解 【0.5%达成】
- 【0.9%】SPOJ7758 Grwoing Strings 解题报告 + AC代码 + 思路 + AC自动机简短总结
- USACO2.4.2 穿越栅栏(简单版本) (重庆一中高2018级信息学竞赛测验2) 解题报告
- 简单的贪心算法 HDU 2037 今年暑假不AC
- 【POJ1011 Sticks】解题报告+思路+代码
- 【算法笔记】动态规划,三个例题(解题思路与C++代码)
- 算法题解题思路及代码(不定时更新)
- 【POJ3740】Easy Finding,解题报告+思路+代码
- 【HDU1072】Nightmare,思路+解题报告+代码
- 【POJ3009 - Curling】 解题报告+思路+代码+教训(看别人的报告过的)
- Kruskal生成树算法的java代码简单实现
- 【poj1164】The Castle,解题报告+思路+代码+数据
- YT04-贪心课堂练习-1001 今年暑假不AC-(6.14日-烟台大学ACM预备队解题报告)