Time Limit: 1 second
Memory Limit: 256 MB网络
问题描述
某个局域网内有n(n<=100)台计算机,因为搭建局域网时工做人员的疏忽,如今局域网内的链接造成了回路,咱们知道若是局域网造成回路那么数据将不听的在回路内传输,形成网路卡的现象。由于链接计算机的网线自己不一样,因此有一些连线不是很畅通,咱们用f(i,j)表示i,j之间链接的畅通程度(f(i,j)<=1000),f(i,j)值越小表示i,j之间链接越通畅,f(i,j)为0表示i,j之间无网线链接。如今咱们须要解决回路问题,咱们将除去一些连线,使得网络中设有回路,而且被除去网线的∑f(i,j)最大,请求出这个最大值。 函数
第一行两个正整数n,k,接下来的k行每行三个正整数i、j、m表示i、j两台计算机之间有网线联通,通畅程度为m。 spa
一个正整数,∑f(i,j)的最大值
code
5 5 1 2 8 1 3 1 1 5 3 2 4 5 3 4 2
8
【题解】排序
若是最后剩余的网线,恰好够n台电脑链接,且少一条线都不行。那么这样的连线方式确定是最佳的。也即用n-1条线链接n台电脑。而后保证这n-1条线是最优的便可。关于克鲁斯卡尔的贪心策略。咱们顺序排了一下。get
咱们在找顺序找边的时候,考虑一下,若是当前边能够链接两个不一样的集合。而你不选,那么以后的边若是能链接这两个集合,那么确定要付出更大的花费。确定不如就选这条边的方案优。input
【代码】it
#include <cstdio> #include <algorithm> using namespace std; struct edge //用结构体 进行排序比较方便。 { int fr,to,w; }; int su,su2,n,k,f[101],tt = 0; //su是全部一开始全部网络的累加和 su2是最小生成树的累加和 edge a[10001]; void input_data() { scanf("%d%d",&n,&k); for (int i = 1;i <= n;i++) //并查集的初始化操做 f[i] = i; for (int i = 1;i <= k;i++) { scanf("%d%d%d",&a[i].fr,&a[i].to,&a[i].w); su+=a[i].w; } } int findfather(int x) //并查集用来寻找根节点的操做,同时压缩路径 { if (f[x]!=x) f[x] = findfather(f[x]); return f[x]; } int cmp(const edge & a,const edge & b) //sort函数的比较函数在algorithm头文件中 { if (a.w < b.w) //不等号决定了你的排序是如何排的 return 1; return 0; } void get_ans() { for (int i = 1;i <= k;i++) //枚举k条边同时累加MST的和 { int x= a[i].fr,y = a[i].to; int r1 = findfather(x),r2 = findfather(y); //若是能联通这两个区域,就连同,由于后面若是再出现 //一条边也能连同这个两个区域,所需的花费确定更大了! if (r1!=r2) { f[r2] = r1; su2+=a[i].w; tt++; if (tt == n-1) //找到n-1条边了就结束。 return; } } } void output_ans() { printf("%d",su-su2); } int main() { //freopen("F:\\rush.txt","r",stdin); input_data(); sort(a+1,a+1+k,cmp); get_ans(); output_ans(); return 0; }