首页 > 其他分享 >YbtOJ 「图论」第2章 最小生成树

YbtOJ 「图论」第2章 最小生成树

时间:2022-08-17 21:00:47浏览次数:53  
标签:图论 int YbtOJ ans 最小 vis cnt head qwq

为什么区间 dp 又咕咕咕了QAQ
于是随机抽取了一个幸运章节来做。
目前处于半摆烂状态。

例题1.繁忙都市

板子。写了下以前几乎没写过的堆优化 Prim。

code
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std; 
const int N=300;
const int M=2e5+5;
int n,m;
int head[N],cnt;
struct node{
	int nxt,to,w;
}e[M];
void add(int u,int v,int w){
	e[++cnt].nxt=head[u];e[cnt].to=v;e[cnt].w=w;head[u]=cnt;
}
int vis[N];
priority_queue<pii,vector<pii>,greater<pii> >q;
int Prim(int s)
{
	int ans=0;
	q.push(pii(0,s));
	while(!q.empty())
	{
		int w=q.top().fi,u=q.top().se;q.pop();
		if(vis[u]) continue;
		ans=max(ans,w);vis[u]=1;
		//cout<<w<<" "<<u<<endl;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(vis[v]) continue;
			q.push(pii(e[i].w,v));
		}
	}
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,u,v,w;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	cout<<n-1<<" "<<Prim(1)<<endl;
	return 0;
}

例题2.新的开始

每个点往 0 号点连一条边代表建立电站,跑最小生成树。

code
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std; 
const int N=305;
const int M=1e5+5;
int n,m,a[N];
int head[N],cnt;
struct node{
	int nxt,to,w;
}e[M];
void add(int u,int v,int w){
	e[++cnt].nxt=head[u];e[cnt].to=v;e[cnt].w=w;head[u]=cnt;
}
int vis[N],tot;
priority_queue<pii,vector<pii>,greater<pii> >q;
int Prim(int s)
{
	int ans=0;
	q.push(pii(0,s));
	while(!q.empty())
	{
		int w=q.top().fi,u=q.top().se;q.pop();
		if(vis[u]) continue;
		ans+=w;vis[u]=1;tot++;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(vis[v]) continue;
			q.push(pii(e[i].w,v));
		}
	}
	return ans;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),add(i,0,a[i]),add(0,i,a[i]);
	for(int i=1;i<=n;i++)
	{
		for(int j=1,w;j<=n;j++)
		{
			scanf("%d",&w);
			if(i!=j) add(i,j,w);
		}
	}
	cout<<Prim(0)<<endl;
	//cout<<n-1<<" "<<Prim(1)<<endl;
	return 0;
}

例题3.公路建设

原先就不在最小生成树上的边,加了其他边也还是不在。
只考虑最小生成树原有的边和新加进来这条就好了。

code
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int n,m,fa[N];
struct node{
	int u,v,w;
}e[N];
int find(int x)
{
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}
int cnt,ans;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++)
	{
		cnt++;
		scanf("%d%d%d",&e[cnt].u,&e[cnt].v,&e[cnt].w);
		if(find(e[cnt].u)!=find(e[cnt].v)) 
		{
			fa[find(e[cnt].u)]=find(e[cnt].v);
			ans+=e[cnt].w;
			if(cnt==n-1) printf("%.1lf\n",ans/2.0);
			else cout<<0<<endl;
			int qwq=cnt;
			while(e[qwq].w<e[qwq-1].w&&qwq>1)
			{
				swap(e[qwq],e[qwq-1]);
				qwq--;
			}
			continue;
		}
		int qwq=cnt;
		while(e[qwq].w<e[qwq-1].w&&qwq>1)
		{
			swap(e[qwq],e[qwq-1]);
			qwq--;
		}
		//for(int i=1;i<=cnt;i++) cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].w<<endl;
		ans=0;int flag=0,now=cnt;cnt=0;
		for(int i=1;i<=n;i++) fa[i]=i;
		for(int i=1;i<=now;i++)
		{
			int u=e[i].u,v=e[i].v,w=e[i].w;
			if(find(u)==find(v)) {flag=i;continue;}
			fa[find(u)]=find(v);cnt++;
			ans+=w;
		}
		while(flag<=cnt)
		{
			swap(e[flag],e[flag+1]);
			flag++;
		}
		if(cnt==n-1) printf("%.1lf\n",ans/2.0);
		else cout<<0<<endl;
	}
	return 0;
}

标签:图论,int,YbtOJ,ans,最小,vis,cnt,head,qwq
From: https://www.cnblogs.com/ying-xue/p/16596738.html

相关文章

  • 初级图论
    拓扑排序即在一个 DAG(有向无环图) 中,我们将图中的顶点按照某种方式进行排序,使得对于任何的顶点u  到 v 的有向边 ,都可以有 u 在 v 的前面。推论:所有能......
  • YbtOJ 「数据结构」第4章 线段树
    不想dp了怎么办?开个新坑吧。例题1.求区间和树状数组不香吗,28行解决(bushi所以懒得打线段树了。code#include<bits/stdc++.h>#defineintlonglongusingnamespac......
  • 洛谷 P6242 【模板】线段树 3 吉司机线段树 区间取最小值 维护历史最大值和区间和
    题目背景本题是线段树维护区间最值操作与区间历史最值的模板。题目描述给出一个长度为 nn 的数列 AA,同时定义一个辅助数组 BB,BB 开始与 AA 完全相同。接下来......
  • 寻找带权图的最小连通:最小生成树
    出现背景树就是没有回路的图for无向图对于不带权的图,想找到一个最小连通边集合,很简答,可以使用生成树,n-1条边可以做到,不唯一对于带权的图,想找到权最小的生成树,称之为最......
  • 一个图论很好用的软件
    Graphviz新版本似乎没有自带的编辑器了,老版本有可以点此下载安装完成后在目录\bin下找gvedit.exe即可使用教程可以官网文档或者B乎简单的几个例子无向图有向图......
  • [2001年NOIP普及组] 最大公约数和最小公倍数问题
     [2001年NOIP普及组]最大公约数和最小公倍数问题思路:可以运用暴力枚举法。先用两个数的乘积=他们的最大公约数*最小公倍数的公式求出乘积num,再在已知范围内暴力搜素能......
  • CF986C AND Graph(图论+二进制连边)
    CF986CANDGraph\(\color{yellow}{\bigstar\texttt{Hint}}\):和每个点连接的点是这个数取反后的子集,考虑将这个点和它的反连边,那么所有对应的数的子集都是同一个连通块内......
  • YbtOJ 「基础算法」第3章 二分算法
    例题1.数列分段二分每段和的最大值。check时从左往右扫,如果当前段的和大于限制则新开一段。code#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+5;i......
  • [2001年NOIP普及组] 最大公约数和最小公倍数问题
    输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数条件:1.P,A是正整数2.要求P,Q以x0为最大公约数,以y0为最小公倍数.试求:满足条件的所有可......
  • [2001年NOIP普及组] 最大公约数和最小公倍数问题
    [2001年NOIP普及组]最大公约数和最小公倍数问题分析:根据题意,求最大公约数和最小公倍数,其中有一个点是两数乘积等于两数的最大公约数乘最小公倍数。知道这一点后,用for循......