首页 > 其他分享 >CF472D题解

CF472D题解

时间:2022-10-06 20:13:59浏览次数:82  
标签:int 题解 短路 邻接矩阵 CF472D maxn inline include

原题

CF472D Design Tutorial: Inverse the Problem


思路概述

题意分析

给定一个 \(n\) 点无向图的两两点对之间距离,即经过最短路算法后的邻接矩阵,要求判断原图是否为一个树。

思路简述

首先回到最短路算法最为关键的松弛操作,以 \(n\) 点图中的Floyd-Warshall算法为例,其核心部分的操作可以表达为:

\[dis_{i,j}=\min\{dis_{i,k}+dis_{k,j}\},1≤k≤n\text{且}k≠i,j \]

由此可知,对于最短路算法后的一个邻接矩阵,其中任意没有连边的两点的距离必然是通过借助其他点进行松弛操作得到。

又根据树的特殊性质可知,若原图为树形结构,则其中存在连边的两点在最短路操作中不会被松弛,即对于最后的邻接矩阵中的每个点而言,与其距离最小的点必然是与其有连边点。因此,本题的突破口即为邻接矩阵中距离最小的点对。

由于是讨论距离最小的点对,则可以引入最小生成树(此处笔者选择用比较顺手的Kruskal)。把邻接矩阵中所有点的距离都看作边,即得到一个完全图。开一个空图来保存加入的边,用于复原原图(下文称其为复原图)。然后把图中所有边升序排序后,每次选取最小的边判定两端点是否联通,若联通图,就在复原图中加上该边,然后重复以上操作,直到整个图完全连通。

最后通过最短路算法在复原图中验证树形结构的存在性。若最短路得到的结果与给出的邻接矩阵不符,则说明原图必然存在环,不满足树形结构的条件。


算法实现

关于邻接矩阵读入

由样例可见,本题读入的邻接矩阵存在十万甚至九万条奇葩数据,包括但不限于自己到自己距离为 \(1\) 的点和权值为 \(0\) 的边。

因此,在读入时就要注意处理这些数据对算法的干扰。

关于验证

最短路可以跑加堆优化的Dijkstra。

但是考虑到本题相当一部分数据是可以形成树的,所以可以考虑直接DFS,在树上的时间复杂度比跑其他最短路算法更快,而且实现更简单。


AC code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<ctime>
#define RI register int
#define RB register bool
using namespace std;
const int maxn=2e3+10;
typedef struct
{
	int pre,dep;
}node;
typedef struct
{
	int u,v,w;
}side;
typedef struct
{
	int u,w,nex;
}graph;
node e[maxn];
side s[maxn*maxn];
graph g[maxn*maxn];
int n,m,cnt,rec;
int fir[maxn],gph[maxn][maxn];
bool jdg=1;
bool v[maxn];
inline bool cmp(side x,side y);
inline void init(int lim);
inline int find(int x);
inline void merge(int x,int y);
inline void add(int x,int y,int w);
inline void dfs(int st,int x,int sp);
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;init(n);
	for(RI i=1,x;i<=n;++i)
		for(RI j=1;j<=n;++j)
		{
			cin >> x;gph[i][j]=x;
			if(i!=j && x) s[++m]=(side){i,j,x};
		}
	sort(s+1,s+m+1,cmp);
	for(RI i=1;i<=m;++i)
		if(find(s[i].u)!=find(s[i].v))
		{
			add(s[i].u,s[i].v,s[i].w);
			merge(s[i].u,s[i].v);
		}
	for(RI i=1;i<=n;++i)
	{
		memset(v,0,sizeof(v));rec=0;
		dfs(i,i,0);
	}	
	if(jdg && rec==n) puts("YES");
	else puts("NO");
	return 0;
}
inline bool cmp(side x,side y)
{
	return x.w<y.w;
}
inline void init(int lim)
{
	for(RI i=1;i<=lim;++i) e[i]=(node){i,1};
	return;
}
inline int find(int x)
{
	return (e[x].pre==x)?x:(e[x].pre=find(e[x].pre));
}
inline void merge(int x,int y)
{
	RI fx=find(x),fy=find(y);
	if(e[fx].dep<=e[fy].dep) e[fx].pre=fy;
	else e[fy].pre=fx;
	if(e[fx].dep==e[fy].dep && fx!=fy) ++e[fy].dep;
	return;
}
inline void dfs(int st,int x,int sp)
{
	if(!v[x])
	{
		v[x]=1;++rec;
		if(sp!=gph[st][x]) jdg=0;
		for(RI i=fir[x];i;i=g[i].nex)
			dfs(st,g[i].u,sp+g[i].w);	
	}
	return;
}
inline void add(int x,int y,int w)
{
	g[++cnt]=(graph){y,w,fir[x]};fir[x]=cnt;
	g[++cnt]=(graph){x,w,fir[y]};fir[y]=cnt;
	return;
}

标签:int,题解,短路,邻接矩阵,CF472D,maxn,inline,include
From: https://www.cnblogs.com/frkblog/p/16758348.html

相关文章

  • Educational Round 30 题解
    ContestLink虽然是unrated,不过秉持着EducationalRound的传统,题还是挺不错的。A.ChoresProblemLink评价:善用STL。由于\(a\)已经排好序了,且\(x\le\min_{i=1......
  • CF1415D XOR-gun 题解 二分答案/贪心
    题目链接https://codeforces.com/problemset/problem/1415/D题目大意给定一个长为\(n\)的不降序列,每次操作可以任选相邻的两个数,并将这两个数替换为两个数按位异或的......
  • C语言基础笔试题解析
    题目在这里:​​c语言笔试面试大全,C语言基础笔试题_Thomas杨大炮的博客-CSDN博客t​​2.C语言程序的三种基本结构都有哪些呢?3. ​​递归调用​​和间接递归调用​​定义​......
  • CF1728A Colored Balls: Revisited 题解
    【题目传送门】思路因为球的总数为奇数,所以肯定会剩下一颗球,因此每次都往数量小的拿,那么最后剩下的球一定是最初数量最多的小球的编号。因为假设最多的少一颗,那么将可以......
  • NOIP2015 T3 乱作题解
    题目看起来好像不是很难啊,为什么我做不出来呢;1.暴力枚举枚举x,y,z的值,再判断是否符合条件;时间复杂度:\(\mathcal{O}(n^3)\)期望得分:\(20pts\)\(Code\):#includ......
  • CF870E题解
    题目大意给你平面上\(n(1\leqslantn\leqslant10^5)\)个点,给出他们的坐标\(x_i,y_i(-10^9\leqslantx_i,y_i\leqslant10^9)\)。对于每个点有三种操作:不进行任何操......
  • P2149 [SDOI2009] Elaxia的路线 题解
    首先考虑分别求出在两个人最短路上的边,这个就是用\(s\)跑一遍最短路,\(t\)跑一遍最短路,然后枚举边\((u,v)\),如果满足\((s\tou)+(u\tov)+(t\tov)=(s\tot)\)那么......
  • 第一道面试题 第一道困难题解答记录
    输入一个奇数n,输出一个由*构成的n阶实心菱形。输入格式一个奇数n。输出格式输出一个由*构成的n阶实心菱形。具体格式参照输出样例。数据范围1≤n≤99输......
  • 【题解】「AGC013D」Piling Up
    传送门题目大意:开始有\(n\)个黑白球在袋子中,但是不知道具体多少黑球白球,有\(m\)次操作,每次从袋子中先拿一个球,再放入一个黑球一个白球,再拿走一个球,求所有初始情况下......
  • 【whk】三调生物-缝合小鼠实验——小鼠肥胖原因 题解
    今天生物考试考了个小鼠肥胖原因的题,写个题解((我根据一位不愿意透露姓名的刘佳兴的描述扒下来了一道似乎很类似的题\((1)\)首先开第一问。他给定了限制是两种原因之一,......