• 最小生成树模板题 P1692


    Description

    给出N个顶点、E条边的连通无向简单图,请你完成下列任务:
    任务1、求边权和最小的生成树(最小生成树)
    任务2、求边权和最大的生成树(最大生成树)
    任务3、求最大边最小的生成树(瓶颈生成树)
    任务4、求最小边最大的生成树(瓶颈生成树)


    Input

    第一行:两个整数N,E(N<=50000,E<=100000),分别表示有N个新岛,E对能直接用电缆连接的岛屿,其中主岛为1。接下来M行:每行三个数u,v,w,1<=u,v<=N,表示岛屿u和v之间可以直接用电缆连接,距离为w(<=100000)。


    Output

    第一行一个整数,表示最小生成树的边权和;第二行一个整数,表示最大生成树的边权和;第三行一个整数,表示最大边最小的生成树中,最大边的权值;第四行一个整数,表示最小边最大的生成树中,最小边的权值;


    Hint

    N<=50000,E<=100000


    Solution

    注意事项:
    1.这个就像有向图那么存就可以了不然排序可能有边排不到,不然用2*m应该也行吧。
    2.循环注意=号。
    3.并查集的union修改的是父亲的值,如果只修改x,y的值父亲的值就没有被修改到。
    4.应该是要用long long的只不过数据太弱了。

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define maxn 100005
    #define inf 0x3f3f3f3f
    using namespace std;
    struct Edge{
    	int u;
    	int v;
    	int w;
    	int next;
    	friend bool operator < (Edge a,Edge b){
    		return a.w<b.w;
    	}
    }edge[maxn];
    int first[maxn],last[maxn],FA[maxn];
    int node,n,m,x,y,z,cnt;
    int ans1,ans2,ans3,ans4;
    void addedge(int u,int v,int w){
    	edge[++node]=(Edge){u,v,w,0};
    	if(first[u]==0)first[u]=node;
    	else edge[last[u]].next=node;
    	last[u]=node;
    }
    void init(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%d",&x,&y,&z);
    		addedge(x,y,z);
    	}
    	for(int i=1;i<=n;i++){
    		FA[i]=i;
    	}
    }
    int dofind(int x){
    	if(FA[x]==x)return x;
    	return FA[x]=dofind(FA[x]);
    }
    void dounion(int x,int y){
    	int dx=dofind(x),dy=dofind(y);
    	if(dx!=dy){
    		FA[dx]=FA[dy];
    	}
    }
    bool dofinD(int x,int y){
    	int dx=dofind(x),dy=dofind(y);
    	return dx==dy;
    }
    void kruskal(){
    	sort(edge+1,edge+m+1);
    	for(int i=1;i<=m;i++){
    		int a=edge[i].u,b=edge[i].v;
    		if(dofinD(a,b))continue;
    		dounion(a,b);
    		ans1+=edge[i].w;
    		ans2=edge[i].w;
    		cnt++;
    		if(cnt==n-1)break;
    	}
    	cnt=0;
    	for(int i=1;i<=n;i++){
    		FA[i]=i;
    	}
    	for(int i=m;i>=1;i--){
    		int a=edge[i].u,b=edge[i].v;
    		if(dofinD(a,b))continue;
    		dounion(a,b);
    		ans3+=edge[i].w;
    		ans4=edge[i].w;
    		cnt++;
    		if(cnt==n-1)break;
    	}
    }
    int main(){
    	init();
    	kruskal();
    	printf("%d
    %d
    %d
    %d
    ",ans1,ans3,ans2,ans4);
    	return 0;
    }
    
  • 相关阅读:
    华为服务器内存插法
    关于公司内部域名称是否要和外部真实域名称对应的问题
    配置Office 365单点登录摘要
    配置Office 365单点登录过程中的一些注意事项
    AADC安装指南
    使用非Web方式从CA申请证书
    爬取某招聘网站的信息
    通过PowerShell启用AADC的密码同步功能
    Azure Active Directory Connect密码同步问题
    Python脚本配合Linux计划任务工作
  • 原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10045223.html
Copyright © 2020-2023  润新知