0
点赞
收藏
分享

微信扫一扫

2月15日学习总结

云卷云舒xj 2022-02-15 阅读 72

1、早上

首先看了一遍啊哈算法上的最小生成树,然后开始做本周的题目,做了两个。(3h)

(1)P3366 【模板】最小生成树 

#include <bits/stdc++.h>
using namespace std;
#define M 200010
#define N 5010
int n,m,fa[N],cnt=0,sum=0;
struct tree{
	int fir;
	int nxt;
	int w;
}p[M];
bool cmp(struct tree a,struct tree b){//按边的权值升序排列 
	if(a.w<b.w) return true;
	else return false;
} 
int find(int t){//找父亲 
	if(fa[t]==t) return t;
	return fa[t]=find(fa[t]);//压缩路径 
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)//初始化父亲 
	  fa[i]=i;
	for(int i=1;i<=m;i++)
	  scanf("%d%d%d",&p[i].fir,&p[i].nxt,&p[i].w);
	sort(p+1,p+m+1,cmp);
	for(int i=1;i<=m;i++){
		int fa1=find(p[i].fir),fa2=find(p[i].nxt);
		if(fa1==fa2) continue;//两点在一个并查集内,就会组成环 
		sum+=p[i].w;
		cnt++;
		fa[fa1]=fa2;//已连接,所以要合并集合 
		if(cnt==n-1) break;
	}
	if(cnt==n-1)//n个点能连n-1条边即可 
	  printf("%d\n",sum);
	else
	  printf("orz\n");   
}  

 (2)P1195 口袋的天空

#include <bits/stdc++.h>
using namespace std;
#define M 10010
int fa[1010],sum,cnt;
struct tree{
	int u;
	int v;
	int w;
}e[M];
bool cmp(struct tree a,struct tree b){//按边的权值升序排列 
	if(a.w<b.w) return true;
	else return false;
} 
int find(int t){//找父亲 
	if(fa[t]==t) return t;
	return fa[t]=find(fa[t]);//压缩路径 
}
int main(){
	int n,m,k;
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)//初始化父亲 
	  fa[i]=i;
	for(int i=1;i<=m;i++)
	  scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+m+1,cmp);
		for(int i=1;i<=m;i++){
		int fa1=find(e[i].u),fa2=find(e[i].v);
		if(fa1==fa2) continue;//两点在一个并查集内,就会组成环 
		sum+=e[i].w;
		cnt++;
		fa[fa1]=fa2;//已连接,所以要合并集合 
		if(cnt==n-k) break;
	}
	if(cnt==n-k)//n朵云朵要组成k个棉花糖,则需要连接n-k根线 
	  printf("%d\n",sum);
	else
	  printf("No Answer\n");   
}

 2、下午

继续做本周的最短路径题目,做出了剩下的三个(4h)。

(1) P2121 拆地毯

#include <bits/stdc++.h>
using namespace std;
#define N 100010
int n,m,k,fa[N],cnt=0,sum=0;
struct tree{
	int u;
	int v;
	int w;
}e[N];
bool cmp(struct tree a,struct tree b){//按边的权值升序排列 
	if(a.w>b.w) return true;
	else return false;
} 
int find(int t){//找父亲 
	if(fa[t]==t) return t;
	return fa[t]=find(fa[t]);//压缩路径 
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)//初始化父亲 
	  fa[i]=i;
	for(int i=1;i<=m;i++)
	  scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=m;i++){
		int fa1=find(e[i].u),fa2=find(e[i].v);
		if(fa1==fa2) continue;//两点在一个并查集内,就会组成环 
		sum+=e[i].w;
		cnt++;
		fa[fa1]=fa2;//已连接,所以要合并集合 
		if(cnt==k) break;
	}
	  printf("%d\n",sum);
}  

 (2)P1991 无线通讯网

#include <bits/stdc++.h>
using namespace std;
int fa[510];
struct tree{
	int u;
	int v;
	double w;
}e[1000001];
bool cmp(struct tree a,struct tree b){//按边的权值升序排列 
	if(a.w<b.w) return true;
	else return false;
} 
int find(int t){//找父亲 
	if(fa[t]==t) return t;
	return fa[t]=find(fa[t]);//压缩路径 
}
int main(){
	int s,p,zb[510][2],k=1,cnt=0;
	double ans;
	scanf("%d%d",&s,&p);
	for(int i=1;i<=p;i++)
	  fa[i]=i; 
	for(int i=1;i<=p;i++)
	  scanf("%d%d",&zb[i][0],&zb[i][1]);
	for(int i=1;i<=p;i++)//求出所有哨塔,两两之间的距离 
		for(int j=i+1;j<=p;j++){
		  e[k].u=i;
		  e[k].v=j;
		  e[k++].w=sqrt((zb[i][0]-zb[j][0])*(zb[i][0]-zb[j][0])+(zb[i][1]-zb[j][1])*(zb[i][1]-zb[j][1]));
		}  
	sort(e+1,e+k+1,cmp);
	for(int i=1;i<=k;i++){
		int fa1=find(e[i].u),fa2=find(e[i].v);
		if(fa1==fa2) continue;//两点在一个并查集内,就会组成环 
		ans=e[i].w;
		cnt++;
		fa[fa1]=fa2;//已连接,所以要合并集合 
		if(cnt==p-1-(s-1)) break;//s个卫星电话可连接s-1线,找到所有需要连接无线电哨塔的数量-卫星电话已连接数量,即可停止 
	}
	printf("%.2lf",ans);	
}

 (3)P2872 [USACO07DEC]Building Roads S

#include <bits/stdc++.h>
using namespace std;
int fa[1010];
struct tree{
	int u;
	int v;
	double w;
}e[5000100];
bool cmp(struct tree a,struct tree b){//按边的权值升序排列 
	if(a.w<b.w) return true;
	else return false;
} 
int find(int t){//找父亲 
	if(fa[t]==t) return t;
	return fa[t]=find(fa[t]);//压缩路径 
}
int main(){
	int n,m,zb[1000][2],k=1,cnt=0;
	double sum=0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	  fa[i]=i;
	for(int i=1;i<=n;i++)
	  scanf("%d%d",&zb[i][0],&zb[i][1]);
	while(m--){
		int u,v;
		scanf("%d%d",&u,&v);
		fa[find(u)]=find(v);//合并 
	} 
	for(int i=1;i<=n;i++)//求出所有点,两两之间的距离 
		for(int j=i+1;j<=n;j++){
		  e[k].u=i;
		  e[k].v=j;
		  e[k++].w=sqrt((double)(zb[i][0]-zb[j][0])*(zb[i][0]-zb[j][0])+(double)(zb[i][1]-zb[j][1])*(zb[i][1]-zb[j][1]));
		}  
	sort(e+1,e+k+1,cmp);
	for(int i=1;i<=k;i++){
		int fa1=find(e[i].u),fa2=find(e[i].v);
		if(fa1==fa2) continue;//两点在一个并查集内,就会组成环 
		sum+=e[i].w;
		cnt++;
		fa[fa1]=fa2;//已连接,所以要合并集合 
		if(cnt==n-1-m) break;//m条边已确定,所以减去
	}
	printf("%.2lf",sum);    
}

 3、晚上

首先过了一遍今天的题目和代码,然后把昨天学的最短路的疑点又看了看。(1h)

今日总共学习时长8h。

举报

相关推荐

0 条评论