首页 > 其他分享 >CodeForces 1142E Pink Floyd

CodeForces 1142E Pink Floyd

时间:2023-07-06 20:34:04浏览次数:61  
标签:Pink typedef int 1142E long pb -- Floyd maxn

洛谷传送门

CF 传送门

感觉很神奇啊,想了挺久的。

如果没有粉色边是容易的。竞赛图中,强连通分量缩点后,拓扑序较小的点向每一个拓扑序比它大的点连边。

利用这个性质,我们维护一个答案集合 \(S\),当 \(|S| \ge 2\) 时,每次随意取出两个点 \(u, v \in S\)。如果边的方向是 \(u \to v\) 那么删掉 \(v\),否则删掉 \(u\)。

正确性显然。如果 \(u, v\) 不在同一个强连通分量,那我们保留了拓扑序较小的强连通分量中的点;如果在,我们随机保留一个就好了。直到 \(|S| = 1\) 时,剩下的唯一点就是在拓扑序最小的强连通分量中。

有粉色边的情况,我们先把粉色边构成的强连通分量缩起来,从入度为 \(0\) 的分量中随便取一个点组成初始的 \(S\)。仍然是做一遍上面的流程,只不过删除一个点时把它入度为 \(0\) 的后继加入 \(S\)。

这样的话,如果我们最后选的点是通过前驱被删掉而加入 \(S\) 的,那它一定能通过绿色边走到它的前驱。它的后继通过粉色边也能走到。如果最后选的点原来没有粉色边相连,由于我们询问的方式,它能只走绿色边到达全部点(感性理解)。

具体实现时可以不需要 Tarjan,类似拓扑排序删除一些构成环的边即可。

由于每次询问都会从 \(S\) 中删除一个点,所以询问次数 \(\le n - 1\)。

code
// Problem: E. Pink Floyd
// Contest: Codeforces - Codeforces Round 549 (Div. 1)
// URL: https://codeforces.com/problemset/problem/1142/E
// Memory Limit: 256 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 100100;

int n, m, ind[maxn];
bool vis[maxn], siv[maxn];
vector<int> G[maxn], T[maxn];

void dfs(int u) {
	vis[u] = siv[u] = 1;
	for (int v : T[u]) {
		if (!siv[v]) {
			G[u].pb(v);
			++ind[v];
		}
		if (!vis[v]) {
			dfs(v);
		}
	}
	siv[u] = 0;
}

inline int ask(int x, int y) {
	printf("? %d %d\n", x, y);
	fflush(stdout);
	scanf("%d", &x);
	return x;
}

void solve() {
	scanf("%d%d", &n, &m);
	while (m--) {
		int u, v;
		scanf("%d%d", &u, &v);
		T[u].pb(v);
	}
	for (int i = 1; i <= n; ++i) {
		if (!vis[i]) {
			dfs(i);
		}
	}
	vector<int> S;
	for (int i = 1; i <= n; ++i) {
		if (!ind[i]) {
			S.pb(i);
		}
	}
	while ((int)S.size() > 1) {
		int u = *(--S.end()), v = *(----S.end());
		if (ask(u, v)) {
			S.erase(----S.end());
			for (int w : G[v]) {
				if (!(--ind[w])) {
					S.pb(w);
				}
			}
		} else {
			S.erase(--S.end());
			for (int w : G[u]) {
				if (!(--ind[w])) {
					S.pb(w);
				}
			}
		}
	}
	printf("! %d\n", S[0]);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:Pink,typedef,int,1142E,long,pb,--,Floyd,maxn
From: https://www.cnblogs.com/zltzlt-blog/p/17533286.html

相关文章

  • 【路径规划】基于A星算法结合floyd和动态窗口法实现机器人栅格地图路径规划附matlab代
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • CF1196F K-th Path 题解 floyd
    题目链接:https://codeforces.com/problemset/problem/1196/F题目大意:给定一个包含\(n\)个节点\(m\)条边的无向图(\(n,m\le2\cdot10^5\))。图中任意两点之间(如果连通的话)都存在一条最短路(节点\(i\)到它自己不算最短路,\(i\)到\(j\)的最短路和\(j\)到\(i\)的最短......
  • Hugging News #0506: StarCoder, DeepFloyd/IF 好多新的重量级模型
    每一周,我们的同事都会向社区的成员们发布一些关于HuggingFace相关的更新,包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等,我们将其称之为「HuggingNews」,本期HuggingNews有哪些有趣的消息,快来看看吧!StarCoder:最新的代码生成LLMBlog:ht......
  • 「学习笔记」Floyd 的应用
    求最短路for(intk=1;k<=n;++k){ for(inti=1;i<=n;++i){ for(intj=1;j<=n;++j){ f[i][j]=min(f[i][j],f[i][k]+f[k][j]); } }}求最小环过程记原图中\(u,v\)之间边的边权为\(val\left(u,v\right)\)。我们注意到Floyd算法......
  • 图的最短路问题(综合详解!!!看这一篇就够了)(spfa-Dijkstra-floyd-模板代码c-)
    文章目录图论:三种最短路及模板模板SPFA算法Floyd算法Dijkstra算法例题与应用反向建边最短路计数1488.最短距离3305.作物杂交4074.铁路与公路图论:三种最短路及模板注意:在这三种算法中我均使用的链式前向星存图,具体方式请看我这篇博客:链式前向星存图详解模板SPFA算法spfa是优化......
  • Floyd算法注意事项
    注意事项:k层循环不能内置Floyd适用于求解全源最短路径问题,即对于给定的图G,求解任意两点之间的最短路径长度。模板#include<bits/stdc++.h>usingnamespacestd;constintN=105;intdis[N][N];voidFloyd(){ memset(dis,0x3f3f3f,sizeof(dis));//初始化为极大值 //......
  • LeetCode 双周赛 102,模拟 / BFS / Dijkstra / Floyd
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。大家好,欢迎来到小彭的LeetCode周赛解题报告。昨晚是LeetCode双周赛第102场,你参加了吗?这场比赛比较简单,拼的是板子手速,继上周掉大分后算是回了一口血......
  • Floyd判圈法
    leetcode141-环形链表其算法应用龟兔赛跑的思想,使用一个slow和fast指针初始都指向链表第一个节点,slow每次向前走一步,fast向前走两步。如果链表无环,那么fast会先走到NULL节点。如果有环,那么当slow和fast都进入环的时候,由于fast比slow走的快,fast总会追上slow。C++代码如下:写法一:......
  • HDU - 1317 XYZZY (floyd + 最长路)
    题目大意:有一种游戏,游戏里面有N个房间,每个房间有相应的能量值,走入该房间就可以得到相应的能量值现在你要从房间1出发,走到房间N,如果中途能量耗尽了,就表示输了,反之,则为赢解题思路:首先得判断一下能不能到达N,这可以用Floyd去判断如果能直接走到N的话,就算赢,否则判断一下,看是否有正环......
  • 多源最短路Floyd本质理解
    \(Floyd\)总结复习Floyd是动态规划的典型体现,其思想从集合角度用闫氏DP分析法即可其关键的性质理解:即外层循环k的理解。\(dist[k][i][j]\)代表(k的取值范围是从1到n),在考......