最小代价生成树:
针对图的概念:
1.生成树中的边的数量为节点数减1
2所有剩余边权加在一起最小的生成树
Kruskal算法:
1 使用并查集:
2 以边排序
//最小生成树模板
#include<iostream>
#include<algorithm>
using namespace std;
struct edge{
int s,e,v;
bool operator<(const edge &b)const{
return this->v<b.v;
}
};
edge edg[200005];
int n,m,ans,my_union[5005],cnt;
void init(){
for(int i=1;i<=n;i++){
my_union[i]=i;
}
}
int find_fa(int x){
if(my_union[x]==x){
return x;
}
return my_union[x]=find_fa(my_union[x]);//路径压缩
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>edg[i].s>>edg[i].e>>edg[i].v;
}
sort(edg,edg+m);
init();
for(int i=0;i<m;i++){
int s=edg[i].s,e=edg[i].e,v=edg[i].v;
int fa=find_fa(s),fb=find_fa(e);
if(fa!=fb){
my_union[fa]=fb;
ans+=v;
cnt++;
if(cnt==n-1){
cout<<ans<<endl;
return 0;
}
}
}
cout<<"orz"<<endl;
return 0;
}
prim算法:
最小生成树不唯一
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
using namespace std;
struct node{
int e,v;
bool operator<(const node&b)const{
return this->v>b.v;
}
};
struct edge{
int e,v,next;
};
edge edg[400005];
//mark 表示某点是否有连通
int n,m,head[5005],mark[5005],ans,cnt,edg_cnt,num[5005];
void add_edg(int a,int b,int c){
edg[edg_cnt].e=b;
edg[edg_cnt].v=c;
edg[edg_cnt].next=head[a];
head[a]=edg_cnt++;
}
int main(){
memset(head,-1,sizeof(head));
memset(num,0x3F,sizeof(num));
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
add_edg(a,b,c);
add_edg(b,a,c);
}
priority_queue<node>que;
que.push((node){n/2,0});//可以随机选
while(!que.empty()){
node temp=que.top();
que.pop();
if(mark[temp.e]==1){
continue;
}
ans+=temp.v;
mark[temp.e]=1;
cnt++;
if(cnt==n){
cout<<ans<<endl;
return 0;
}
for(int i=head[temp.e];i!=-1;i=edg[i].next){
int e=edg[i].e,v=edg[i].v;
if(mark[e]==0&&num[e]>v){
que.push((node){e,v});
num[e]=v;//num[x]为连接到x的某条边的权值
}
}
}
cout<<"orz"<<endl;
return 0;
}
题目描述
某国有n个城市,它们互相之间没有公路相通,因此交通十分不便。为解决这一“行路难”的问题,政府决定修建公路。修建公路的任务由各城市共同完成。
修建工程分若干轮完成。在每一轮中,每个城市选择一个与它最近的城市,申请修建通往该城市的公路。政府负责审批这些申请以决定是否同意修建。
政府审批的规则如下:
(1)如果两个或以上城市申请修建同一条公路,则让它们共同修建;
(2)如果三个或以上的城市申请修建的公路成环。如下图,A申请修建公路AB,B申请修建公路BC,C申请修建公路CA。则政府将否决其中最短的一条公路的修建申请;
(3)其他情况的申请一律同意。
一轮修建结束后,可能会有若干城市可以通过公路直接或间接相连。这些可以互相:连通的城市即组成“城市联盟”。在下一轮修建中,每个“城市联盟”将被看作一个城市,发挥一个城市的作用。
当所有城市被组合成一个“城市联盟”时,修建工程也就完成了。
你的任务是根据城市的分布和前面讲到的规则,计算出将要修建的公路总长度。
输入格式
第一行一个整数n,表示城市的数量。(n≤5000)
以下n行,每行两个整数x和y,表示一个城市的坐标。(-1000000≤x,y≤1000000)
输出格式
一个实数,四舍五入保留两位小数,表示公路总长。(保证有惟一解)
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
using namespace std;
struct node{
int e;
double v;
bool operator<(const node&b)const{
return this->v>b.v;
}
};
int n,xy[5005][2],mark[5005],cnt;
double num[5005],ans;
double func(int a,int b){
long long t1=xy[a][0]-xy[b][0];
long long t2=xy[a][1]-xy[b][1];
return sqrt(t1*t1+t2*t2);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>xy[i][0]>>xy[i][1];
num[i]=999999999999999;
}
priority_queue<node>que;
que.push((node){1,0});//可以随机选
while(!que.empty()){
node temp=que.top();
que.pop();
if(mark[temp.e]==1){
continue;
}
ans+=temp.v;
//mark[temp.e]=1;
cnt++;
mark[temp.e]=1;
if(cnt==n){
//cout<<ans<<endl;
printf("%.2f\n",ans);
return 0;
}
for(int i=1;i<=n;i++){
//int e=edg[i].e,v=edg[i].v;
if(mark[i]==0&&i!=temp.e){
double t=func(temp.e,i);
if(num[i]>t){
num[i]=t;
que.push((node){i,t});
}
}
}
}
//cout<<"orz"<<endl;
return 0;
}
题目描述
国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;
每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。
任意两个配备了一条卫星电话线路的哨所(两边都ᤕ有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 D,这是受收发器的功率限制。收发器的功率越高,通话距离 D 会更远,但同时价格也会更贵。
收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 D。你的任务是确定收发器必须的最小通话距离 D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。
输入格式
从 wireless.in 中输入数据第 1 行,2 个整数 S 和 P,S 表示可安装的卫星电话的哨所数,P 表示边防哨所的数量。接下里 P 行,每行两个整数 x,y 描述一个哨所的平面坐标(x, y),以 km 为单位。
输出格式
输出 wireless.out 中
第 1 行,1 个实数 D,表示无线电收发器的最小传输距离,精确到小数点后两位。
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<algorithm>
using namespace std;
struct edge{
int s,e;
double v;
};
bool cmp(const edge&a,const edge&b){
return a.v<b.v;
}
edge edg[250005];
int k,n,my_union[505],xy[505][2],edg_cnt,cnt;
void init(){
for(int i=1;i<=n;i++){
my_union[i]=i;
}
}
// int n,xy[5005][2],mark[5005],cnt;
// double num[5005],ans;
// double func(int a,int b){
// long long t1=xy[a][0]-xy[b][0];
// long long t2=xy[a][1]-xy[b][1];
// return sqrt(t1*t1+t2*t2);
// }
int find_fa(int x){
if(my_union[x]==x){
return x;
}
return my_union[x]=find_fa(my_union[x]);
}
int main(){
cin>>k>>n;
init();
for(int i=1;i<=n;i++){
cin>>xy[i][0]>>xy[i][1];
for(int j=1;j<i;j++){
int t1=xy[i][0]-xy[j][0];
int t2=xy[i][1]-xy[j][1];
edg[edg_cnt].s=i;
edg[edg_cnt].e=j;
edg[edg_cnt++].v=sqrt(t1*t1+t2*t2);
}
//num[i]=999999999999999;
}
sort(edg,edg+edg_cnt,cmp);
for(int i=0;i<edg_cnt;i++){
int s=edg[i].s,e=edg[i].e;
double v=edg[i].v;
int fa=find_fa(s),fb=find_fa(e);
if(fa!=fb){
my_union[fa]=fb;
cnt++;
if(cnt==n-k){
printf("%.2f\n",v);
return 0;
}
}
}
//cout<<"orz"<<endl;
return 0;
}