BNUZ [kuangbin带你飞] 最小生成树

52 篇文章 1 订阅
34 篇文章 0 订阅
本文探讨了Prim算法在道路构建(A-JungleRoads)、最小生成树构建(Kruskal算法)以及空间站建设中的应用,同时涉及TruckHistory中的字符串相似度问题,通过最小生成树求解最短路径。
摘要由CSDN通过智能技术生成

A - Jungle Roads

Prim算法:

#include<string>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
int a[550][550], d[550], v[550],k;
int n,m,ans;

void prim(){
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=1;
	ans=0;
	for(int i=1;i<n;i++){
		int x=0,minnum=INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=1;
        if(minnum!=INF)	
		ans+=minnum;
		for(int y=1;y<=n;y++){
			if(!v[y])d[y]=min(d[y],a[x][y]);
		}
	}
	printf("%d\n",ans);
}

int main(){
    while(scanf("%d", &n)&&n)
    {
	memset(a,INF,sizeof(a));
	for(int i=1;i<=n;i++)a[i][i]=0;
	for(int i=1;i<=n-1;i++){
		int k1;
		string c1;
		cin>>c1>>k1;
		for(int j=1;j<=k1;j++){
			int k2;
			string c2;
			cin>>c2>>k2;
			int tmp1=c1[0]-'A'+1;
			int tmp2=c2[0]-'A'+1;
			a[tmp1][tmp2]=a[tmp2][tmp1]=min(a[tmp1][tmp2],k2);
		}
	}
	prim();
	}
	return 0;
}

B:Networking

Kruskal算法

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct rec{int x,y,z; }edge[500010];
int fa[100010],n,m,ans;
bool operator<(rec a,rec b){
	return a.z<b.z;
}
int get(int x){
	if(x==fa[x])return x;
	return fa[x]=get(fa[x]);
}
int main(){
	while(scanf("%d",&n)&&n){
		ans=0;
	memset(fa,0,sizeof(fa));
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	cin>>edge[i].x>>edge[i].y>>edge[i].z;
	sort(edge+1,edge+1+m);
	for(int i = 1;i<=n;i++)fa[i]=i;
	for(int i = 1;i<=m;i++){
		int x=get(edge[i].x);
		int y=get(edge[i].y);
		if(x==y)continue;
		fa[x]=y;
		ans+=edge[i].z;
	}
	cout<<ans<<endl;
	}
	return 0;
}

C - Building a Space Station

#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
double a[550][550],d[550], v[550],k;
int n;
double ans;
double x[550],y[550],z[550],r[550];

void prim(){
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=1;
	ans=0;
	for(int i=1;i<n;i++){
		int x=0;
		double minnum=INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=1;
        if(minnum!=INF)	
		ans+=minnum;
		for(int y=1;y<=n;y++){
			if(!v[y])d[y]=min(d[y],a[x][y]);
		}
	}
	printf("%.3lf\n",ans);
}

double dis(double a,double b,double c,double d,double e,double f,double g,double h){
	return sqrt( (a-b)*(a-b) + (c-d)*(c-d) + (e-f)*(e-f) )-g-h;
}
int main(){
    while(scanf("%d", &n)&&n)
    {
	memset(a,INF,sizeof(a));
	for(int i=1;i<=n;i++)a[i][i]=0;
	for(int i=1;i<=n;i++){
		scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]);
	}
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++){
			double zz=dis(x[i],x[j],y[i],y[j],z[i],z[j],r[i],r[j]);
			if(zz>0)a[i][j]=a[j][i]=zz;
			else a[i][j]=a[j][i]=0;
		}
	}
	prim();
	}
	return 0;
}

D - Constructing Roads

#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
ll a[550][550],d[550], v[550];
int n;
ll ans;
double x[550],y[550],z[550],r[550];

void prim(){
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=1;
	ans=0;
	for(int i=1;i<n;i++){
		int x=0;
		ll minnum=INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=1;
        if(minnum!=INF)	
		ans+=minnum;
		for(int y=1;y<=n;y++){
			if(!v[y])d[y]=min(d[y],a[x][y]);
		}
	}
	printf("%lld\n",ans);
}

int main(){
    scanf("%d", &n);
	memset(a,INF,sizeof(a));
	for(int i=1;i<=n;i++)a[i][i]=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%lld",&a[i][j]);
		}
	}
	int k;
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		a[x][y]=a[y][x]=0;
	}
	prim();
	
	return 0;
}

E - Truck History

题意:俩个不同字符串间的相同位置的不同字符个数就是俩个字符串的距离然后用最小生成树找出答案

#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2500;
ll a[N][N],d[N], v[N];
char str[N][10];
int n;
ll ans;

void prim(){
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=1;
	ans=0;
	for(int i=1;i<n;i++){
		int x=0;
		ll minnum=INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=1;
        if(minnum==INF)break;	
		ans+=minnum;
		for(int y=1;y<=n;y++){
			if(!v[y])d[y]=min(d[y],a[x][y]);
		}
	}
	printf("The highest possible quality is 1/%d.\n",ans);
}

int main(){
    while(scanf("%d", &n)!=EOF&&n){
    memset(a,INF,sizeof(a));
	for(int i=1;i<=n;i++){
		scanf("%s",str[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			int tmp=0;
			for(int k=0;k<7;k++){
				if(str[i][k]!=str[j][k])tmp++;
			}
			a[i][j]=a[j][i]=tmp;
		}
	}
	prim();	
	}
	return 0;
}

F - Arctic Network

#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include<algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2500;
double a[N][N],d[N];
bool v[N];
double dis[N];
double x[N],y[N];
int n,k;

double prim(){
	double ans = 0;
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=1;
	ans=0;
	for(int i=1;i<n;i++){
		int x=0;
		double minnum=INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=true;
        //if(minnum==INF)break;	
		ans+=minnum;
		dis[k++]=minnum;
		//cout<<dis[k-1]<<" ";
		for(int y=1;y<=n;y++){
			if(!v[y])d[y]=min(d[y],a[x][y]);
		}
	}
	return ans;
}

double dd(double x1,double x2,double y1,double y2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

int main(){
	int T,m;
	scanf("%d",&T);
    while(T--){
    scanf("%d%d", &m,&n);
    k=0;
    memset(dis,0,sizeof(dis));
    memset(a,INF,sizeof(a));
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&x[i],&y[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j)a[i][j]=0;
			else a[i][j]=a[j][i]=dd(x[i],x[j],y[i],y[j]);
		}
	}
	prim();	
	sort(dis,dis+k);
	//cout<<"k="<<k<<endl;
	printf("%.2lf\n",dis[k-m]);
	}
	return 0;
}

G - Highways

#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include<algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1050;
double a[N][N],d[N];
bool v[N];
int dis[N];
double x[N],y[N];
int n,k;

void prim(){
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i] , dis[i] = 1;
	v[1]=1;
	for(int i=1;i<n;i++){
		int x=0;
		double minnum=INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=true;
        if(a[dis[x]][x]!=0)printf("%d %d\n",dis[x],x);
		d[x]=0;
		for(int y=1;y<=n;y++){
			if(!v[y]&&d[y]>d[x]+a[x][y]){
				d[y]=d[x]+a[x][y];
				dis[y]=x;
			}
		}
	}
	return;
}

double dd(double x1,double x2,double y1,double y2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

int main(){
    scanf("%d",&n);
    memset(a,INF,sizeof(a));
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&x[i],&y[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j)a[i][j]=0;
			else a[i][j]=a[j][i]=dd(x[i],x[j],y[i],y[j]);
		}
	}
	int q;
	scanf("%d",&q);
	while(q--){
		int xx,yy;
		scanf("%d%d",&xx,&yy);
		a[xx][yy]=a[yy][xx]=0;
	}
	prim();	
	return 0;
}

H - Agri-Net

#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include<algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200;
ll a[N][N],d[N];
bool v[N];
ll dis[N];
int n;

ll prim(){
	ll ans=0;
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=1;
	for(int i=1;i<n;i++){
		int x = 0;
		ll minnum = INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=true;
		d[x]=0;
		ans += minnum;
		for(int y=1;y<=n;y++){
			if(!v[y]&&d[y]>d[x]+a[x][y]){
				d[y]=d[x]+a[x][y];
			}
		}
	}
	return ans;
}

int main(){
    while(scanf("%d",&n)!=EOF){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%lld",&a[i][j]);
		}
	}
	printf("%lld\n",prim());	
	}	
	return 0;
}

I - Borg Maze

题解:BFS+MST,非常好玩的一个题,先把图中每个A和S当成点然后用BFS找出每个点之间的距离,再用MST找出答案

#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define ll long long
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 300;
const int MAXN = 3000;
int a[MAXN][MAXN],d[MAXN];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int mp[N][N];
char str[N][N];
bool v[MAXN],vis[N][N];
int n,m;

struct p{
	int x,y,z;
};

int prim(int n){
	ll ans=0;
	memset(v,0,sizeof(v));
	for(int i = 0; i < n; i++)
    d[i] = a[0][i];
    d[0]=0;
	v[0]=1;
	for(int i=1;i<n;i++){
		int x = 0;
		int minnum = INF;
		for(int j=0;j<n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		v[x]=true;
		d[x]=0;
		ans += minnum;
		for(int y=1;y<=n;y++){
			if(!v[y]&&d[y]>d[x]+a[x][y]){
				d[y]=d[x]+a[x][y];
			}
		}
	}
	return ans;
}

void bfs(int i,int j){
	int x=i,y=j;
	memset(vis,0,sizeof(vis));
	queue<p>q;
	vis[i][j] = true;
	a[mp[i][j]][mp[i][j]]=0;
	p tmp2;
	tmp2.x=i,tmp2.y=j,tmp2.z=0;
	q.push(tmp2);
	while(!q.empty()){
		p tmp1=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int tx=tmp1.x+dx[i];
			int ty=tmp1.y+dy[i];
			if(tx<n&&tx>=0&&ty<m&&ty>=0&&str[tx][ty]!='#'&&!vis[tx][ty]){
				if(mp[tx][ty]!=-1)
				a[mp[x][y]][mp[tx][ty]]=tmp1.z+1;
				p tmp3;
				tmp3.x=tx,tmp3.y=ty,tmp3.z=tmp1.z+1;
				q.push(tmp3);
				vis[tx][ty]=true;
			}
		}
	}
}

int main(){
	int T;
	scanf("%d",&T); 
	char s[30];
    while(T--){
		scanf("%d%d ",&m,&n);

		for(int i = 0;i < n;i++)
		{
			gets(str[i]);
		}
		int pos=0;
		memset(mp,-1,sizeof(mp));
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(str[i][j]=='A'||str[i][j]=='S'){
					mp[i][j]=pos++;
				}
			}
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(mp[i][j]!=-1){
					bfs(i,j);
				}
			}
		} 
		int ans = prim(pos);
		printf("%d\n",ans);
	}	
	return 0;
}

J - The Unique MST

找出是否有重复的路

#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define ll long long
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 200;
const int MAXN = 3005;
int a[N][N],d[MAXN];
bool v[MAXN];
int n,m,k,ans,f,flag;

int prim(int n){
	memset(v,0,sizeof(v));
	for(int i = 1; i <= n; i++)
    d[i] = a[1][i];
	v[1]=true;
	ans=flag=0;
	for(int i=1;i<n;i++){
		int x = 0;
		int minnum = INF;
		for(int j=1;j<=n;j++){
			if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
		}
		f = 0;
		for(int j=1;j<=n;j++){
			if(v[j]&&a[j][x]==minnum)f++;
		}
		if(f>1){
		flag=1;
		return 0;	
		}
		v[x]=true;
		ans+=minnum;
		for(int y=1;y<=n;y++){
			if(!v[y]&&d[y]>a[x][y]){
				d[y]=a[x][y];
			}
		}
	}
	return ans;
}


int main(){
	int T;
	scanf("%d",&T); 
    while(T--){
		scanf("%d%d ",&n,&m);
		memset(a,INF,sizeof(a));
		for(int i=1;i<=n;i++)a[i][i]=0;
		for(int i=1;i<=m;i++){
			int a1,a2,a3;
			scanf("%d%d%d",&a1,&a2,&a3);
			a[a1][a2]=a[a2][a1]=min(a[a2][a1],a3);
		}
		int sum = prim(n);
		if(flag)printf("Not Unique!\n");
		else printf("%d\n",sum);
	}	
	return 0;
}

K - 还是畅通工程

#include<iostream>
using namespace std;
#include<map>
#include<algorithm>
#include<string>
#include<cstring>
#define ll long long

int fa[101000],n,m,ans;

struct rec{
    int x,y,z;
    bool operator <(const rec b)const {
        return z<b.z;
    }
}edge[501000];

int get(int key){
    if(fa[key]==key)return key;
    return fa[key]=get(fa[key]);
}

int main(){
    while(scanf("%d",&n)!=EOF&&n){
    
    m=n*(n-1)/2;
    
    ans=0;
    
    for(int i=1;i<=n;i++)fa[i]=i;
        
    for(int i=1;i<=m;i++){
    int x,y;
    scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
    } 
    
    sort(edge+1,edge+1+m);
    
    for(int i=1;i<=m;i++){
    int tx=get(edge[i].x);
    int ty=get(edge[i].y);
    if(tx==ty)continue;
    fa[tx]=ty;
    ans+=edge[i].z;
    }
    int f=0;
    
    for(int i=1;i<=n;i++){
        if(fa[i]==i){
            f++;
        }
    }
    
    if(f!=1)printf("?\n");
    else printf("%d\n",ans);    
    }
    return 0;
} 

L与A重了

M - 畅通工程再续

#include<iostream>
using namespace std;
#include<map>
#include<algorithm>
#include<string>
#include<cstring>
#define ll long long

int fa[101000],n,m;
double ans;

struct P{
    int x,y;
}p[501000];

struct rec{
    int x,y;
    double z;
    bool operator <(const rec b)const {
        return z<b.z;
    }
}edge[501000];

int get(int key){
    if(fa[key]==key)return key;
    return fa[key]=get(fa[key]);
}

double d(int x1,int x2,int y1,int y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}


int main(){
    int T;
    while(scanf("%d",&T)!=EOF){
    while(T--){
    scanf("%d",&n);
    
    ans=0;
    
    for(int i=1;i<=n;i++)fa[i]=i;
        
    for(int i=1;i<=n;i++){
    scanf("%d%d",&p[i].x,&p[i].y);
    } 
    
    int pos=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i!=j){
                double z = d(p[i].x,p[j].x,p[i].y,p[j].y);
                if(z<10||z>1000)continue;
                edge[pos].x=i;
                edge[pos].y=j;
                edge[pos].z=z;
                //printf("%d -> %d -> z = %lf\n",i,j,edge[pos].z);
                pos++;
            }
        }
    }
    //cout<<"pos = "<<pos<<endl;
    
    //pos/=2;
    
    //cout<<"pos = "<<pos<<endl;
    
    sort(edge+1,edge+1+pos);
    
    for(int i=1;i<=pos;i++){
    int tx=get(edge[i].x);
    int ty=get(edge[i].y);
    if(tx==ty)continue;
    fa[tx]=ty;
    ans+=edge[i].z;
    }
    
    int f=0;
    
    for(int i=1;i<=n;i++){
        if(fa[i]==i){
            f++;
        }
    }
    
    if(f!=1)printf("oh!\n");
    else printf("%.1lf\n",ans*100);    
    }    
    }
    return 0;
} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值