最小生成树

最小生成树

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\n");
				return 0;
			}
		}
	}
	
	printf("%lld\n",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\n",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\n",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\n",ans2);
	
	return 0;
	
}
posted @ 2020-12-04 10:59  雾隐  阅读(101)  评论(0编辑  收藏  举报