局域网

某个局域网内有 n 台计算机和 k 条 双向 网线,计算机的编号是 1∼n。由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。

注意

  • 对于某一个连接,虽然它是双向的,但我们不将其当做回路。本题中所描述的回路至少要包含两条不同的连接。
  • 两台计算机之间最多只会存在一条连接。
  • 不存在一条连接,它所连接的两端是同一台计算机。

因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用 \(f(i,j)\) 表示 \(i,j\) 之间连接的畅通程度,\(f(i,j)\) 值越小表示 \(i,j\) 之间连接越通畅。

现在我们需要解决回路问题,我们将除去一些连线,使得网络中没有回路且不影响连通性(即如果之前某两个点是连通的,去完之后也必须是连通的),并且被除去网线的 \(Σf(i,j)\) 最大,请求出这个最大值。

输入格式

第一行两个正整数 \(n,k\)

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

输出格式

一个正整数,表示被除去网线的 \(Σf(i,j)\)的最大值。

数据范围

1≤n≤100
0≤k≤200
1≤f(i,j)≤1000

输入样例:

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

输出样例:

8

思路

裸的求最小生成树问题,用的普利姆算法。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=111;
typedef pair<int,int> PII;
int h[N],cnt,vis[N],dis[N];
struct eg{
    int v,c,nex;
}e[N*4];
void ad(int u,int v,int c){
    e[++cnt]={v,c,h[u]};
    h[u]=cnt;
}
int prim(int st){
    priority_queue<PII,vector<PII>,greater<PII> > heap;
    heap.push({0,st});
    memset(dis,0x3f,sizeof dis);
    dis[st]=0;
    int res=0;
    while(!heap.empty()){
        int u=heap.top().second;
        heap.pop();
        if(vis[u]) continue;
        vis[u]=1;
        res+=dis[u];
        for(int i=h[u];~i;i=e[i].nex){
            int v=e[i].v,cc=e[i].c;
            if(!vis[v]&&dis[v]>cc){
                dis[v]=cc;
                heap.push({cc,v});
            }
        }
    }
    return res;
}
int main(){
    int n,m;
    cin>>n>>m;
    memset(h,-1,sizeof h);
    int res=0;
    for(int i=1,u,v,c;i<=m;++i){
        cin>>u>>v>>c;
        ad(u,v,c);
        ad(v,u,c);
        res+=c;
    }
    int rres=0;
    for(int i=1;i<=n;++i){
        if(!vis[i]) rres+=prim(i);
    }
    cout<<res-rres;
}
原文地址:https://www.cnblogs.com/jjl0229/p/12884023.html