zoukankan      html  css  js  c++  java
  • 洛谷 P2820 局域网(prim)

    题目链接

    https://www.luogu.org/problemnew/show/P2820

    题目背景

    某个局域网内有n(n<=100)台计算机,由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用f(i,j)表示i,j之间连接的畅通程度,f(i,j)值越小表示i,j之间连接越通畅,f(i,j)为0表示i,j之间无网线连接。

    题目描述

    需要解决回路问题,我们将除去一些连线,使得网络中没有回路,并且被除去网线的Σf(i,j)最大,请求出这个最大值。

    输入输出格式

    输入格式:

    第一行两个正整数n k

    接下来的k行每行三个正整数i j m表示i,j两台计算机之间有网线联通,通畅程度为m。

    输出格式:

    一个正整数,Σf(i,j)的最大值

    输入输出样例

    输入样例:

    5 5
    1 2 8
    1 3 1
    1 5 3
    2 4 5
    3 4 2
    

    输出样例:

    8

    说明

    f(i,j)<=1000

    解题思路

    首先,我们需要了解一下有关最小生成树的知识。

    名词解释:

    • 最小生成树:对于带权图,权值和最小的生成树

    • 最小瓶颈生成树:对于带权图,最大权值最小的生成树

    • 最小生成树一定是最小瓶颈生成树

    蒟蒻不理解,换一种解释:

    • 生成树:在一幅图中将所有n个点连接起来的n-1条边所形成的树

    • 最小生成树:边权之和最小的生成树

    算法:

      Prim算法或者Kruskal算法。但是一般都会使用Kruskal算法,因为它实用性更强,更加灵活,而且不用建图。

      但是在这里我们介绍prim算法

    prim算法:

      prim算法的思想和dijstra很像——都是红白点思想。初始状态下,除第一个点(可以是任意一个点)为红点外,所有的点都是白点,每一次循环找出距离这个红点最近的白点,把它变成红点,然后再用这个点去更新其他的白点。就像这样,知道所有的点都变成红点。

    这个题就是求被除去的长度最大,就是剩下的总长度最小,剩下的总长度就是最小生成树的边权和,被除去的总长度=原来总长度-最小生成树的边权和。

    其中对memset不懂的推荐我的另一篇博客:https://www.cnblogs.com/yinyuqin/p/10162716.html

    具体实现请见代码:

     1 #include<iostream>
     2 #include<cstring>        //memset的头文件 
     3 using namespace std;
     4 int m[105][105],n,k,cnt1,cnt2;    //m用来存图(邻接矩阵存图) 
     5 int a[105];                //a[i]存的是每个点到最小生成树的最短距离 
     6 int ok[105];            //ok[i]存的是i这个点是否已经在最小生成树上 
     7 int main(){
     8     cin>>n>>k;
     9     for(int i=1;i<=k;i++){
    10         int a,b,c;
    11         cin>>a>>b>>c;
    12         m[a][b]=m[b][a]=c;        //这个一个无向图。 
    13         cnt1+=c;                //存原图的边权和 
    14     }
    15     memset(a,0x7f,sizeof(a));    //先把每个点到最小生成树的距离设置为无穷大。 
    16     a[1]=0;                        //将点1加入最小生成树,点1到最小生成树的距离设置为0。 
    17     for(int j=1;j<=n;j++){        //要保证每一个点都在最小生成树里面,就需要循环n次。 
    18         int minn=0;
    19         for(int i=1;i<=n;i++){    //找到距离最小生成树最小的白点 
    20             if(!ok[i]&&((a[i]<a[minn])||minn==0)) minn=i;
    21         }
    22         ok[minn]=1;                //将白点变为红点,加入最小生成树 
    23         for(int i=0;i<=n;i++){    //更新与这个点相邻的其他白点距最小生成树的距离 
    24             if(m[minn][i]&&!ok[i]) a[i]=min(m[minn][i],a[i]);//取最小值 
    25         }
    26     }
    27     for(int i=1;i<=n;i++) cnt2+=a[i];    //统计最小生成树的边权和 
    28     cout<<cnt1-cnt2;            //相减即为答案 
    29     return 0;
    30 }
    AC代码
  • 相关阅读:
    Python·Jupyter Notebook
    CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)概念区分理解
    tensorflow学习
    语料库
    资源 | 数十种TensorFlow实现案例汇集:代码+笔记
    Tensorlayer
    利用 TFLearn 快速搭建经典深度学习模型
    十分钟搞定pandas
    利用python进行数据分析之pandas入门
    Pandas
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/10779387.html
Copyright © 2011-2022 走看看