首页 > 其他分享 >题解 Friendly Spiders

题解 Friendly Spiders

时间:2023-07-17 21:34:49浏览次数:32  
标签:node cout int 题解 Spiders push adj Friendly dis

Friendly Spiders

带有技巧的最短路。

如果 \(u\) 能到 \(v\),说明 \(\gcd(u,v)>1\),也就是有相同因子。

所以我们考虑对于每个数 \(u\),向他的所有质因子连一条长度为 \(1\) 的边,这样我们从 \(u\) 到 \(v\) 需要走两步,最终答案除以 \(2\) 即可。

每次遇到一个新的因子,都要新建节点。

需要注意的是,如果 \(u\) 的质因子中有真实存在的点,那么边权要设为 2,否则会少算。

最后跑一边最短路或 BFS 就行了。

复杂度 \(O(n \log n)\)。

code:

#include <bits/stdc++.h>
using namespace std;
const int N = 6e5 + 5, inf = INT_MAX >> 2;
int n, a[N], s, t, dis[N], vis[N], pre[N], id[N], id2[N], tot;
struct node{
	int v, w;
	node(int v = 0, int w = 0):v(v), w(w){}
};
vector<node> adj[N];
void add(int u, int v, int w) {
	adj[u].push_back(node(v, w));
	adj[v].push_back(node(u, w));
}
void get(int w) {
	int x = a[w];
	for (int i = 2; i <= sqrt(x); ++i) {
		if (x % i == 0) {
			if (vis[i]) add(w, id[i], 2);
			if (!id2[i]) id2[i] = ++tot;
			add(w, id2[i], 1);
			while (x % i == 0) x /= i;
		}
	}
	if (x != 1) {
		if (vis[x]) add(w, id[x], 2);
		if (!id2[x]) id2[x] = ++tot;
		add(w, id2[x], 1);
	}
}
queue<int> q;
stack<int> st;
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n;
	tot = n;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i]; id[a[i]] = i; vis[a[i]] = 1;
		get(i);
	}
	for (int i = 1; i <= tot; ++i) dis[i] = inf;
	cin >> s >> t;
	dis[s] = 2;
	q.push(s);
	while (!q.empty()) {
		int u = q.front(); q.pop();
		for (int i = 0; i < adj[u].size(); ++i) {
			int v = adj[u][i].v, w = adj[u][i].w;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				pre[v] = u;
				q.push(v);
			}
		}
	}
	if (dis[t] == inf) {
		cout << -1 << endl;
		return 0;
	}
	cout << dis[t] / 2 << endl;
	int cur = t;
	while (cur != s) {
		st.push(cur);
		cur = pre[cur];
	}
	st.push(s);
	while (!st.empty()) {
		while (st.top() > n) st.pop();
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;
	return 0;
}

标签:node,cout,int,题解,Spiders,push,adj,Friendly,dis
From: https://www.cnblogs.com/HQJ2007/p/17561291.html

相关文章

  • 题解 The Human Equation
    TheHumanEquation思维题。我们考虑每次\(a\)数组加一减一对于其前缀和\(sum\)的影响。可以发现,假设相邻两次加一和减一的位置分别为\(l\)和\(r\),那么\(sum\)在\([l,r)\)内会加一。先减后加也同理。所以,一次加减操作相当于将\(sum\)若干段连续序列加一或减一。......
  • 题解 [ARC153B] Grid Rotations
    [ARC153B]GridRotations有思维含量的一题。我们横纵坐标分开考虑,对于每一个矩形,每次操作会使其内部元素的横坐标上下对调。纵坐标也同理,左右对调。而这种反转操作我们显然可以直接用两棵文艺平衡树维护,复杂度\(O(n\logn)\)。标程的做法更巧妙一下。我们可以把一条链收尾......
  • 题解 Yet Another Minimization Problem
    YetAnotherMinimizationProblem神仙题。第一眼看上去就是DP。定义\(f_{i,j}\)表示当前点\(i\),分\(j\)段的最小费用。\(f_{i,j}=\min(f_{i,j},f_{k,j-1}+val_{k+1,i})\)然后发现复杂度\(O(n^2k)\),直接T飞,需要优化。我们发现\(j\)那一维可以滚掉,也就是只考虑第......
  • 题解 P4322 [JSOI2016]最佳团体
    P4322[JSOI2016]最佳团体分数规划+树形背包。可以根据推荐关系建出一颗树,然后如果选了一点,则该点到根上的所有点都必须选。二分\(mid\),定义每个结点的权值,然后判断选\(k+1\)个节点的最大值是否大于\(0\)。设\(f_{i,j}\)为当前节点\(i\),在其子树内选了\(j\)个节点,最......
  • 题解 Bracket Insertion
    BracketInsertion神仙DP题,不愧是tourist。容易发现,括号序列一共有\(1\cdot3\cdot5...\cdot(2n-1)\)种生成方式。假如(为\(1\),)为\(-1\),那么一个序列合法的充要条件为:最小前缀和为\(0\),且以\(0\)结尾。现在考虑维护这些前缀和。如果我们在当前序列某一位后插......
  • 题解 P2276 [HNOI2002]农场的果树
    首先可以观察出一颗\(n\)个节点的二叉树,当其字典序最小的时候,其形态为一条向右偏的链,当其字典序最大的时候,是一条向左偏的链。由于每一种编码对应唯一的一颗二叉树,我们可以先建树。然后考虑树上分治,尝试以下三种方式:变大右子树的字典序变大左子树的字典序,并将右子树变成......
  • 题解 P7640 [BalticOI 2006 Day 2] CITY PLANNING
    首先我们定义“圈”为与原点距离相等的点集。...3.....323...32123.3210123.32123...323.....3...暴力:把圈放到堆里,然后每次取出代价最小的一圈,修改当前圈的楼层,向外圈拓展。正解:考虑二分。如果是二分最终答案,我们会发现......
  • 题解 P7250 [BalticOI 2012 Day1] 山峰
    通过观察,可以发现此题和最小生成树十分相似(两个地点之间途经的最小值最大)。于是可以考虑这么做:通过bfs将每一个块预处理出来,并记录其编号、高度、类型(是否为高地)以及边缘的点。将每一个块按高度从大到小排序。依次枚举每个块:对于当前要处理的块,枚举其边界的所有点,......
  • 题解 AT3726 [ARC087B] FT Robot
    首先可以观察到一个非常重要的性质:对于一次前进的操作,如果前面有奇数次转向,则走上下,否则走左右。(当然如果一开始就前进就只能走右)于是我们可以将其拆成许多的“块”,并分成两类,即前进方向为左右还是上下。然后对于两个维度分别dp。\(f_{i},_{j}=f_{i-1},_{j-val}\|\f_{i-......
  • Charles抓取https请求及常见问题解决
    一、背景APP测试的时候,通常都需要通过抓包工具抓取各类请求,查看接口的入参、返回值等,用于分析定位问题。常用的抓包工具有fiddler、charles等,抓取http的请求比较简单,https的请求稍显复杂。由于更喜欢charles的页面风格,本篇文章主要介绍以下两点:1、Charles如何抓取电脑端和手机端的......