457. 最优布线问题
[问题描述]
学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们之间有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。
当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。
现在由你负责连接这些计算机,你的任务是使任意两台计算机都连通(不管是直接的或间接的)。
[输入格式]
输入文件wire.in,第一行为整数n(2<=n<=1500),表示计算机的数目。此后的n行,每行n个整数。第x+1行y列的整数表示直接连接第x台计算机和第y台计算机的费用。
使所有节点都联通,且路径总权值最小,裸的最小生成树。Kruscal水过。
其实正解是Prim……Kruscal会T一个点。然后开O2就A啦~\(≧▽≦)/~
#include<cstdio>
#include<iostream>
#include<algorithm>
#define COGS
using namespace std;
const int maxn=1500*1500+1;//数组,要开足!!!
int m,n,cnt=-1;
int p[1501],w[maxn],r[maxn],u[maxn],v[maxn];
void Init(){
int x;
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>x;
if(i<j && x>0){
cnt++;
u[cnt]=i;v[cnt]=j;w[cnt]=x;//记录每条边
}
}
}
}
int cmp(const int i,const int j){return w[i]<w[j];}//以权重为关键字排序,便于Kruskal贪心
int find(int x){return p[x]==x?x:p[x]=find(p[x]);}//借助并查集实现的Kruskal
void Kruskal(){
int ans=0;
for(int i=0;i<n;i++)p[i]=i;
for(int i=0;i<n*n;i++)r[i]=i;//初始化
sort(r,r+(n*n),cmp);
for(int i=0;i<n*n;i++){
int e=r[i];int x=find(u[e]);int y=find(v[e]);
if(x!=y){ans+=w[e];p[x]=y;}//不在同个连通分量,加入MST
}
cout<<ans;
}
int main()
{
ios::sync_with_stdio(false);
#ifdef COGS
string FileName="wire";
freopen((FileName+".in").c_str(),"r",stdin);
freopen((FileName+".out").c_str(),"w",stdout);
#endif
Init();
Kruskal();
}