某个局域网内有 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;
}