xmuOJ 安全网络 ver.3
来源
http://acm.xmu.edu.cn/JudgeOnline/problem.php?cid=1023&pid=1
描述
Problem B: 安全网络 ver.3
Time Limit: 2500 MS Memory Limit: 64 MB
Submit: 691 Solved: 176
[Submit][Status][Web Board]
Description
现在有个一个内部局域网络,里面有N台机器。为了某种安全原因的考虑,有些机器之间是无法直接通讯的,即使可以通讯,机器与机器之间的通讯都是经过加密的。由于不同机器之间传输的内容不同,所以他们通讯采用的加密级别也不大相同。不同的加密级别导致破解的难度不一样,越高的加密级别破解需要的时间也越多。如果我们获得了编号为i的机器的完全控制权,且机器i和机器j可以直接通讯,另外我们破解了机器i和机器j之间的加密信息,那么我们就得到了机器j的完全控制权。
现在你通过了某种手段入侵了1号机器,得到了这台机器的完全控制权,为了扩大劳动果实,你准备对其余的机器也在你的控制当中,但是由于需要破解加密信息才能控制其它机器,你又不想浪费太多时间在破解上,现在你来算算你至少需要多少时间才能完全控制整个网络。
Input
输入的第一行是两个正整数N(2 <= N <= 100,000) M(0 < M <= 200,000),表示机器的数目和允许通讯的机器对数。
输入的第二行开始到第M+1行,每行3个整数,A B T( 1 <= A, B <= N, T <= 10,000, A ≠ B),表示机器A和机器B之间可以互相通讯,且破解这个通讯的时间是T。输入保证不存在重复的AB对。
Output
输出完全控制所有机器的最少时间。如果无法满足要求则输出-1。
Sample Input
4 4
1 2 4
1 3 9
2 3 2
4 3 1
Sample Output
7
分析
一道求解最小生成树的题目,可用kruscal来解。问题不一定有解,可用变量cnt记录加入最小生成树中的顶点的个数,如果小于N,则无解。
详细讲解 傻子都能看懂的并查集入门
注意点
//函数father(a) 容易写成 father[a],所以还是用 find_fa()比较好
//N M 容易混淆 测试数据一定要让 N!=M
测试数据:
4 6
1 2 4
1 3 9
2 3 2
4 3 1
1 4 7
2 4 3
out:7
//题目要求里的顶点序号从1开始,所以程序中的for语句也应当从1开始
//cnt 应当初始化为1,而不是0
//time 是oj平台预定义变量
代码
运行情况
第一遍超时了
进行路径压缩的优化后
优化效果非常明显。
AC代码
#include <iostream>
#include<stdlib.h>
#include <vector>
#include<stdio.h>
#include<string>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct edge
{
int x;
int y;
int w;
}edge;
int length = 0;//记录MIT 总权重
int* fa;
int cnt=1; //记录最小生成树中顶点的个数
int cmp(const void* a, const void* b)
{
return (*(edge*)a).w-(*(edge*)b).w;
}
int father(int x)
{
return x == fa[x] ? x :fa[x] = father(fa[x]) ; // fa[x] = father(x) 是为了路径压缩
// if (fa[x] == x)
// return x;
// else
// return father(fa[x]);
}
int union_set(int a,int b,int w){
a = father(a);
b = father(b);
if(a==b)
return -1;
else
{
fa[a] = b;
length+=w;
cnt++;
return 1;
}
}
int main()
{
int N,M;
int i,j,k;
//initialize
scanf("%d %d", &N,&M);
fa = (int*)malloc(sizeof(int)*(N+1));
for (i =1 ; i <=N ; i++)
fa[i]=i;
edge* e = (edge*)malloc(sizeof(edge)*(M+1));
for (i =1 ; i <=M ; i++)
scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].w);
qsort(e+1,M,sizeof(edge),cmp);
//O(|E|log|E|)
for (i =1 ; i <=M ; i++)
union_set(e[i].x,e[i].y,e[i].w);
//output
if(cnt!=N) //被破译的点没有N个
cout<<-1<<endl;
else
{
cout<<length<<endl;
}
return 0;
}
/*
4 6
1 2 4
1 3 9
2 3 2
4 3 1
1 4 7
2 4 3
out:
*/
//函数father(a) 容易写成 father[a],所以还是用 find_fa()比较好
//N M 容易混淆 测试数据一定要让 N!-M
//题目要求里的顶点序号从1开始,所以程序中的for语句也应当从1开始
//cnt 应当初始化为1,而不是0
//time 是oj平台预定义变量
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。