• 最小生成树


    最小生成树

    kruskal

    运用贪心的思想,每次将边权最小且两端点均未被标记的点加入,并将点标记,重复执行直到有 (n-1) 条边已选

    #include<iostream>
    #include<cstdio>
    #include<math.h>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    
    const ll maxn=2e5+10;
    ll n,m,cnt,ans;
    ll fa[maxn];
    
    struct node
    {
    	ll u,v,w;
    } s[maxn];
    
    inline bool cmp(node a,node b)
    {
    	return a.w<b.w;
    }
    
    inline ll find(ll x)
    {
    	if(fa[x]==x) return x;
    	return fa[x]=find(fa[x]);
    }
    
    inline void kruskal()
    {
    	for(int i=1;i<=m;i++)
    	{
    		ll uu=s[i].u,vv=s[i].v;
    		ll eu=find(uu),ev=find(vv);
    		
    		if(eu==ev) continue;
    		
    		fa[ev]=eu;
    		
    		ans+=s[i].w;
    		
    		cnt++;
    	
    		if(cnt==n-1) break;
    	}
    }
    
    int main(void)
    {
    	scanf("%lld %lld",&n,&m);
    	
    	for(int i=1;i<=n;i++) fa[i]=i;
    	
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%lld %lld %lld",&s[i].u,&s[i].v,&s[i].w);
    	}
    	
    	std::sort(s+1,s+m+1,cmp);
    	
    	kruskal();
    	
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=i+1;j<=n;j++)
    		{
    			if(find(i)!=find(j))
    			{
    				printf("orz
    ");
    				return 0;
    			}
    		}
    	}
    	
    	printf("%lld
    ",ans);
    	
    	return 0;
    }
    

    prim

    # include <cstring>
    # include <cstdio>
    # include <algorithm>
    # include <iostream>
    using namespace std;
    # define N 1001
    # define INF 0x3f3f3f3f
    int A[N][N],dist[N];
    bool vis[N];
    int n,m,ans;
    int prim(int root)
    {
        int x,ans=0;
        memset(dist,0x3f,sizeof(dist));
        memset(vis,0,sizeof(vis));
        dist[root]=0;
        for(int i=1;i<=n;i++)
        {
            x=0;
            for(int j=1;j<=n;j++)
            if(!vis[j]&&(x==0||dist[j]<dist[x]))x=j;
            vis[x]=true;
            for(int y=1;y<=n;y++)
                if(!vis[y])dist[y]=min(dist[y],A[x][y]);
        }
        for(int i=1;i<=n;i++)
        {
           if(dist[i]==INF)return INF;
           ans+=dist[i];
        }
        return ans;
    }
    int main()
    {
        int x,y,z;
        scanf("%d%d",&n,&m);
        memset(A,0x3f,sizeof(A));
        for(int i=1;i<=n;i++)A[i][i]=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            A[y][x]=A[x][y]=min(A[x][y],z);
        }
        int ans=prim(1);
        if(ans==INF)puts("impossible");
        else printf("%d
    ",ans);
        return 0;
    }
    

    次小生成树

    只需先求出一个最小生成树,然后将树边用次大的非树边依次尝试替换即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #define ll long long 
    using namespace std;
    
    const ll INF=999999999999999; 
    const ll maxn=3e5+10;
    ll n,m,cnt,ans,ans2=INF,flag;
    ll fa[maxn],dep[maxn],vis[maxn],b[maxn];
    ll f[maxn][30],g1[maxn][30],g2[maxn][30];
    vector<pair<ll,ll> > e[maxn];
    struct node
    {
    	ll x,y,z;
    } s[maxn];
    
    inline ll read()
    {
    	ll x=0,f=1;char ch=getchar();
    	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    	return x*f;
    }
    
    inline ll find(ll x)
    {
    	if(fa[x]==x) return x;
    	return fa[x]=find(fa[x]);
    }
    
    inline bool cmp(node a,node b)
    {
    	return a.z<b.z;
    }
    
    inline void kruskal()
    {
    	sort(s+1,s+m+1,cmp);
    	
    	for(int i=1;i<=m;i++)
    	{
    		ll eu=find(s[i].x),ev=find(s[i].y);
    		if(eu==ev) continue;
    		ans+=s[i].z;
    		fa[ev]=eu;
    		e[s[i].y].push_back(make_pair(s[i].x,s[i].z));
    		e[s[i].x].push_back(make_pair(s[i].y,s[i].z));
    		b[i]=1;
    	}
    }
    
    inline void dfs(ll x,ll v)
    {
    	f[x][0]=v;
    	for(int i=0;i<e[x].size();i++)
    	{
    		ll y=e[x][i].first;
    		if(y==v) continue;
    		dep[y]=dep[x]+1;
    		g1[y][0]=e[x][i].second;
    		g2[y][0]=-INF;
    		dfs(y,x);
    	}
    }
    
    inline void pre()
    {
    	for(int i=1;i<=25;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			f[j][i]=f[f[j][i-1]][i-1];
    			g1[j][i]=max(g1[j][i-1],g1[f[j][i-1]][i-1]);
    			g2[j][i]=max(g2[j][i-1],g2[f[j][i-1]][i-1]);
    			if(g1[j][i-1]>g1[f[j][i-1]][i-1]) g2[j][i]=max(g2[j][i],g1[f[j][i-1]][i-1]);
    			else if(g1[j][i-1]<g1[f[j][i-1]][i-1]) g2[j][i]=max(g2[j][i],g1[j][i-1]);
    		}
    	}
    }
    
    inline ll LCA(ll p1,ll p2)
    {
    	if(dep[p1]<dep[p2]) swap(p1,p2);
    	
    	for(int i=25;i>=0;i--)
    	{
    		if(dep[f[p1][i]]>=dep[p2])
    		{
    			p1=f[p1][i];
    		}
    	}
    	if(p1==p2) return p2;
    	for(int i=25;i>=0;i--)
    	{
    		if(f[p1][i]!=f[p2][i])
    		{
    			p1=f[p1][i];
    			p2=f[p2][i];
    		}
    	}
    	return f[p1][0];
    }
    
    inline ll q_LCA(ll p1,ll p2,ll w)
    {
    	ll sum=-INF;
    	for(int i=25;i>=0;i--)
    	{
    		if(dep[f[p1][i]]>=dep[p2])
    		{
    			if(w!=g1[p1][i]) sum=max(g1[p1][i],sum);
    			else sum=max(sum,g2[p1][i]);
    			p1=f[p1][i];
    		}
    	}
    	
    	return sum;
    }
    
    int main(void)
    {
    	n=read();
    	m=read();
    	
    	for(int i=1;i<=n;i++) fa[i]=i;
    	
    	for(int i=1;i<=m;i++)
    	{
    		s[i].x=read();s[i].y=read();s[i].z=read();
    	}
    	
    	kruskal();
    	g2[1][0]=-INF;
    	dep[1]=1;
    	dfs(1,-1);
    	pre();
    	
    //	printf("%lld
    ",ans);
    	
    	for(int i=1;i<=m;i++)
    	{
    		if(!b[i])
    		{
    			ll mid=LCA(s[i].x,s[i].y);
    			ll QAQ=q_LCA(s[i].x,mid,s[i].z);
    			ll QWQ=q_LCA(s[i].y,mid,s[i].z);
    			ans2=min(ans2,ans-max(QAQ,QWQ)+s[i].z);
    		}
    	}
    	
    	printf("%lld
    ",ans2);
    	
    	return 0;
    	
    }
    
  • 相关阅读:
    谷歌浏览器提示Adobe Flash Player因过期而遭到阻止
    Oracle 查看表空间剩余与创建空间语法
    招标
    iphone刷机各种错误
    oracle 创建dblink
    imp-00002 无法打开。。
    oracle 大字段clob检索
    (一)EasyUI 使用——基本概念
    使用 Google 高级搜索的一些技巧
    (四)Maven构建多模块项目
  • 原文地址:https://www.cnblogs.com/jd1412/p/14084660.html
Copyright © 2020-2023  润新知