ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P6628 [省选联考 2020 B 卷] 丁香之路 欧拉路+最小生成树

2020-11-17 09:31:29  阅读:324  来源: 互联网

标签:度数 ch val P6628 省选 frm int maxn 联考


题意:

戳这里

分析:

  • 暴力

据说状压+特判有50分,但我只会暴搜+特判,所以只有20分(我好菜)

  • 正解

前置芝士 :欧拉路径,生成树

这道题目的边权给的很巧妙,由基本不等式可以推出

任意两点之间直接连边不会比通过其他点相连更劣

所以对于每一个人来说,最后的路径可以看成是一条欧拉通路,欧拉通路具有一个性质:恰好有 \(0\) 或 \(2\) 个奇度数顶点 ,在本题中这两个奇度数顶点就是 \(s\) 和 \(i\) ,我们就按照欧拉通路的性质,对于每一个除 \(s,i\) 以外的奇度数顶点,找到一个离他最近的奇度数顶点与它配对,最后使得这些点的度数都为偶数

但是,这样还没有完,因为可能存在一条边,右端点和左端点连边成环的情况,也就是说最后连接完的图可能被分为了多个连通块,那么我们考虑用最小的代价将图联通,也就是求一个最小生成树

复杂度\(O(n^2log)\)

代码:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	inline int read()
	{
		int 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;
	}
	
	const int maxn = 2505;
	int fa[maxn],bel[maxn];
	int n,m,s;
	long long sum,ans;
	vector<int> v[maxn];
	struct edge
	{
		int frm,to,val;
		edge(){}
		edge (int frm,int to,int val):frm(frm),to(to),val(val){}
		bool operator <(const edge &b)const
		{
			return val<b.val;
		}
	};
	
	int find(int x)
	{
		return fa[x]==x?x:fa[x]=find(fa[x]);
	}
	
	void work()
	{
		int a,b;
		n=read();m=read();s=read();
		for(int i=1;i<=n;i++) fa[i]=i;
		for(int i=1;i<=m;i++)
		{
			a=read();b=read();
			v[a].push_back(b);
			v[b].push_back(a);
			sum+=abs(a-b);
			fa[find(a)]=find(b);
		}
		for(int i=1;i<=n;i++) bel[i]=find(i);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++) fa[j]=j;
			v[s].push_back(i);v[i].push_back(s);
			fa[find(bel[s])]=find(bel[i]);
			int pre=0;ans=sum;
			for(int j=1;j<=n;j++)
			{
				if(v[j].size()&1)
				{
					if(pre)
					{
						ans+=j-pre;
						for(int k=pre;k<j;k++) fa[find(bel[k])]=find(bel[j]);
						pre=0;
					}
					else pre=j;
				}
			}
			vector<edge> e;
			for(int j=1;j<=n;j++)
			{
				if(v[j].size())
				{
					if(pre&&find(bel[j])!=find(bel[pre])) e.push_back(edge(bel[j],bel[pre],abs(j-pre)));
					pre=j;
				}
			}
			sort(e.begin(),e.end());
			for(int j=0,k=e.size();j<k;j++)
			{
				if(find(e[j].frm)!=find(e[j].to))
				{
					fa[find(e[j].frm)]=find(e[j].to);
					ans+=2*e[j].val;
				}
			}
			printf("%lld ",ans);
			v[s].pop_back();v[i].pop_back();
		}
	}

}

int main()
{
	zzc::work();
	return 0;
}

标签:度数,ch,val,P6628,省选,frm,int,maxn,联考
来源: https://www.cnblogs.com/youth518/p/13992557.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有