fzoj1613:联络员
http://fzoj.xndxfz.com/JudgeOnline/problem.php?id=1613
题目描述
Tyvj已经一岁了,网站也由最初的几个用户增加到了上万个用户,随着Tyvi网站的逐步壮大,管理员的数目也越来越多,现在你身为Tyvj管理层的联络员,希望你找到一些通信渠道,使得管理员两两都可以联络(直接或者间接都可以)。Tyvj是一个公益性的网站,没有过多利润,所以你要尽可能地使费用少才可以。
目前你已经知道,Tyvi的通信渠道分为两大类,一类是必选通信渠道,无论价格多少,你都需要把所有的都选择上;还有一类是选择性的通信渠道,你可以从中挑选一些作为最终管理员联络的通信渠道。数据保证给出的通行渠道可以让所有的管理员连通。
输入
第1行:n、m表示Tyvi一共有n个管理员,有m个通信渠道。
第2行到m+1行:每行四个非负整数p,u,v,w,当p=1时,表示这个通信渠道为必选通信渠道;;当p=2时,表示这个通信渠道为选择性通信渠道;u,v,w表示本条信息描述的是u、v管理员之间的通信渠道,u可以收到v的信息,v也可以收到u的信息,w表示费用。
输出
最小的通信费用。
样例输入
5 6
1 1 2 1
1 2 3 1
1 3 4 1
1 4 1 1
2 2 5 10
2 2 5 5
样例输出
9
还是最小生成树,prim 加并查集
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=2001,MAXM=10001;
struct line{
int fir;int p1;int p2;int len;
};
bool com(line a,line b){
if(a.fir!=b.fir)return a.fir<b.fir;
return a.len<b.len;
}
int n,m,sum=0,father[MAXN];
line lilen[MAXM];
int getFather(int t){
if(father[t]==t) return t;
father[t]=getFather(father[t]);
return father[t];
}
void unionn(int x,int y){
int A,B;
A=getFather(x);
B=getFather(y);
if(A!=B)father[A]=B;
}
int main(){
int i,p,u,v,w,j=1;
freopen("联络员.txt","r",stdin);
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)father[i]=i;
for(i=1;i<=m;i++){
scanf("%d%d%d%d",&p,&u,&v,&w);
lilen[i].fir=p;
lilen[i].p1=u;
lilen[i].p2=v;
lilen[i].len=w;
if(p==1){
sum+=w;
unionn(lilen[i].p2,lilen[i].p1);
}
}
sort(lilen+1,lilen+m+1,com);
for(i=1;i<=m;i++){
if(lilen[i].fir==1)continue;
if(getFather(lilen[i].p1)!=getFather(lilen[i].p2)){
unionn(lilen[i].p2,lilen[i].p1);
sum+=lilen[i].len;
}
}
printf("%d",sum);
return 0;
}