poj-1861
来源:互联网 发布:三国杀网络错误请重试 编辑:程序博客网 时间:2024/04/27 07:09
// 596K 141MS G++#include <cstdio>#include <cstring>#include <algorithm>using namespace std;struct Connetcions { int begin; int end; int length; char left;};int cmp(const void * a, const void * b) { return (*((Connetcions *)a)).length - (*((Connetcions *)b)).length;}struct union_find_member { int setId; // begin from 1, 0 means not filled yet. // int Prev; // int prevLength;};typedef struct union_find_member union_find_member;typedef struct Connetcions Connetcions;union_find_member UF_set[1010];Connetcions connections[15010];int leftConnectionsNum;int hubNum;int connectionNum;int maxlength = 0;int getSetId(int nodeId) { if (UF_set[nodeId].setId == 0) { return 0; } int curSetId = UF_set[nodeId].setId; while(UF_set[curSetId].setId != curSetId) { curSetId = UF_set[curSetId].setId; } UF_set[nodeId].setId = curSetId; return curSetId;}char UF_fill(int beginId, int endId, int connectionlength) { int beginSetId = getSetId(beginId); int endSetId = getSetId(endId); // printf("%d -> %d, %d -> %d\n", beginId, beginSetId, endId, endSetId); // if begin and end all no filled before if (beginSetId == 0 && endSetId == 0) { UF_set[beginId].setId = beginId; UF_set[endId].setId = beginId; } else if (!beginSetId && endSetId) { UF_set[beginId].setId = endSetId; } else if (beginSetId && !endSetId) { UF_set[endId].setId = beginSetId; // printf("A %d %d\n", beginSetId, UF_set[endId].setId); } else if (beginSetId && endSetId) { if (beginSetId != endSetId) { UF_set[endSetId].setId = beginSetId; UF_set[endId].setId = beginSetId; } else { // has all filled, no need this cable, and becuase sorted before, // so it must >= current cable. return 0; } } return 1;}int main() { while(scanf("%d %d", &hubNum, &connectionNum) != EOF) { maxlength = 0; memset(UF_set, 0, sizeof(UF_set)); memset(connections, 0, sizeof(connections)); leftConnectionsNum = 0; for (int i = 1; i <= connectionNum; i++) { int beginId; int endId; int connectionlength; scanf("%d %d %d", &beginId, &endId, &connectionlength); connections[i-1].begin = beginId; connections[i-1].end = endId; connections[i-1].length = connectionlength; } qsort(connections, connectionNum, sizeof(Connetcions), cmp); for (int i = 0; i < connectionNum; i++) { // printf("%d %d %d\n", connections[i].begin, // connections[i].end, connections[i].length); if (UF_fill(connections[i].begin, connections[i].end, connections[i].length)) { connections[i].left = 1; maxlength = connections[i].length > maxlength ? connections[i].length: maxlength; leftConnectionsNum++; } } printf("%d\n%d\n", maxlength, leftConnectionsNum); for (int i = 0; i < connectionNum; i++) { if (connections[i].left) { printf("%d %d\n", connections[i].begin, connections[i].end); } } }}
算是道并查集的简单题,不过我一开始被搞晕了,纠结于最短路径的问题,并且,一开始,还想着把hub之前的连接关系直接集成到并查集里做,但是后面才发现,简直是自坑,因为并查集这种数据结构不适合来存储这种关系(其实真存也行的), 就另开一个数组来储存最后可以被留下来的cable连接,这道题其实也可以用最小生成树做的。
用并查集做,有个很关键的预处理步骤,那就是把所有输入的cable 按照 长度来进行从小达大的排序,这样才能达到题目的目的,尽量的保留长度最短,并且尽量去掉多余的cable,那么接下来就是并查集的标准操作了,并查集在这里的作用,就是检查输入的两个hub是否已经能被之前的cabl连通了,只需判断这些hub是否属于并查集的同一个集即可(因为这里的cable是双向的), 对于输入的一个cable,有两个hub, A 和B,那么,在将其加入到并查集中时,会有这些case:
case1: A 和 B 之前都没有被添加过, 那么直接将A 和B做为一个集, A作为B的集合Id.
case2: A添加过,B没有添加过,那么直接将B加入到A的集合中,B的集合id 是 A的集合Id.
case3: 和case2相反,A B倒换.
case4: A和B之前都已经被添加过了,又会有两个子case:
sub-case1: A 和 B的集合Id一样,说明之前加入的cable已经能够将A 与 B连通,并且因为之前已经排过序,因此之前的cable各自的长度一定<=当前这段cable,
那么,按照题意,这段cable可以被去掉,直接pass,这里显示出了排序的重要性,否则,可能虽然A B都连通了,但是连接他们的cable可能比这次的要长, 注意题目 没有要求从长度最短,而是要求一段cable最短。
sub-case2: A 和 B不一个集合,那么就将B的set的top元素的setId设为A的setId, 即将此B所属集合并入到A的集合。
在上面的处理过程中,还要收集被留下来的cable的长度最大值作为输出.
- poj 1861
- POJ 1861
- poj 1861
- POJ 1861
- poj 1861
- poj 1861
- poj-1861
- POJ 1861
- poj 1861
- POJ 1861
- POJ 1861
- POJ 1861 Networks
- POJ 1861 Network
- poj 1861 Network
- POJ 1861 Network
- poj 1861 network
- poj 1861 network
- poj 1861 network
- mysql存储过程error-This function has none of DETERMINISTIC, NO SQL
- ServerTokens
- Linux网络流量实时监控ifstat iftop命令详解
- console.log功能记录~
- linux SVN服务器创建版本库
- poj-1861
- 上传图片js判断图片尺寸和格式
- 项目中遇到的坑 1
- Live555做本地采集视频直播
- 2.Spring 环境的搭建
- 补充linux删除文件硬盘空间爆满
- Android中listview滚动条常见
- jQuery.Validate验证库 转
- 发生的阵列