把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

APIO2013 道路费用【最小生成树】

题目链接

题目解析

根据k的范围,不难想到我们2k枚举所有新边是否在MST中,然后再加入原始边,计算出答案取最值。

但是这样做复杂度过不去。

先考虑把k条新边加进去,然后再按照Kruskal算法加入n1k条原始边,形成一棵树。由于原始边的权值各不相同,那么目前加入的这些原始边集合是唯一确定的。

又因为在MST里的新边条数最多为k,那么加入的原始边数量不会比现在更少,又是从小到大加边,目前已经加入的原始边一定一直在MST中。

所以我们可以把这些固定的原始边连在一起,进行缩点。

那么现在图中只剩下k+1个结点了(我们还差k条边没有连,想成一棵k条边的树,结点个数就是k+1了)

诶嘿,然后我们现在发现刚才的那个做法,它又可以了,所以那么做就行了。


►Code View

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
#define N 100005
#define M 200005
#define INF 0x3f3f3f3f
#define LL long long
int rd()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f*x;
}
struct node{
	int u,v,w;
}e[M],g[25],e2[M];
int cnt;
bool cmp(node p,node q)
{
	return p.w<q.w;
}
int n,m,k;
int p[N],pe[N];
int id[N],tot;
int rt;
struct un{
	int f[N];
	void Init()
	{
		for(int i=1;i<=n;i++)
			f[i]=i,f1[i]=i;
	}
	int Find(int x)
	{
		if(f[x]==x) return x;
		return f[x]=Find(f[x]);
	}
	bool Union(int u,int v)
	{
		u=Find(u),v=Find(v);
		if(u==v) return 0;
		if(u<v) f[u]=v;
		else f[v]=u;
		return 1;
	}
}A,B;

int main()
{
	n=rd(),m=rd(),k=rd();
	A.Init();
	B.Init();
	for(int i=1;i<=m;i++)
		e[i].u=rd(),e[i].v=rd(),e[i].w=rd();
	for(int i=1;i<=k;i++)
	{
		g[i].u=rd(),g[i].v=rd();
		A.Union(g[i].u,g[i].v);
	}
	for(int i=1;i<=n;i++)
		p[i]=rd();
	sort(e+1,e+m+1,cmp);
	int num=k;
	for(int i=1;i<=m;i++)
	{
		if(A.Union(e[i].u,e[i].v))
		{
			num++;
			B.Union(e[i].u,e[i].v);
		}
		if(num==n-1) break;
	}
	for(int i=1;i<=n;i++)
		if(B.Find(i)==i)
			id[i]=++tot;//缩点
	for(int i=1;i<=n;i++)
		pe[id[B.Find(i)]]+=p[i];//缩点
	rt=id[B.Find(1)];
	A=B;
	for(int i=1;i<=m;i++)
		if(B.Union(e[i].u,e[i].v))
			e2[++cnt]=e[i];//可能加入的原始边
	for(int i=1;i<=k;i++)
		g[i].u=id[A.Find(g[i].u)],g[i].v=id[A.Find(g[i].v)];//缩点
	for(int i=1;i<=cnt;i++)
		e2[i].u=id[A.Find(e2[i].u)],e2[i].v=id[A.Find(e2[i].v)];//缩点
	
	for(int S=0;S<(1<<k);S++)
	{
		
	}
	return 0;
}



posted @   Starlight_Glimmer  阅读(68)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示