ICode9

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

CF1142E Pink Floyd

2022-05-19 09:32:39  阅读:151  来源: 互联网

标签:Pink 粉边 int CF1142E read Floyd 管辖 front include


一、题目

点此看题

二、解法

首先考虑 \(m=0\) 的情况怎么做,发现如果某个点连出去一个菊花的情况,我们都有点搞不定。不难感受到本题直接确定起始点再验证的思路是困难的,我们不妨考虑逐步筛选起始点

套用类似归纳的方法,假设我们现在有集合 \(S\) 表示可能的起始点,其中的点可能管辖一些点,那么走到它就可以走到它管辖的点。我们考虑任取 \(S\) 中的两个点 \((u,v)\) 并询问,那么如果有边 \(u\rightarrow v\),我们把 \(v\) 也纳入 \(u\) 的管辖范围,就可以把 \(v\) 从 \(S\) 中删去,这样就归纳到了子问题,不难分析询问次数 \(O(n)\)(如果边是 \(v\rightarrow u\) 那么处理方式同理)

回到本题,考虑更普遍的情况。由于本题是只能经过同色边,那么在构造中我们尽量要把绿边和粉边独立开来

考虑这样构造初始的 \(S\):选出一个子集,使得它们之间没有粉边连接,并且它们可以到达所有点,换句话说就是这些点通过粉边可以管辖所有点。那么这样场上是不存在粉边的,就可以套用 \(m=0\) 的方法。

但是删除一个点之后,可能 \(S\) 还需要一些改动,那么我们在一开始的时候保留一个拓扑图,发现 \(S\) 中的点都是入度为 \(0\) 的点,在删除一个点之后类似拓扑排序把新释放出来的,入度为 \(0\) 的点加入即可。这样最后剩下的点就是答案,因为它可以通过粉边到达自己初始管辖的点,可以通过绿边到达已经被删除的点。

时间复杂度 \(O(n+m)\)

#include <cstdio>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
const int M = 100005;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,vis[M],in[M],d[M];vector<int> g[M],to[M];
void dfs(int u)
{
	vis[u]=in[u]=1;
	for(int v:g[u])
	{
		if(!in[v]) to[u].push_back(v),d[v]++;
		if(!vis[v]) dfs(v);
	}
	in[u]=0;
}
int ask(int u,int v)
{
	printf("? %d %d\n",u,v);
	fflush(stdout);
	return read();
}
signed main()
{
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read();
		g[u].push_back(v);
	}
	queue<int> q;
	for(int i=1;i<=n;i++)
		if(!vis[i]) dfs(i);
	for(int i=1;i<=n;i++)
		if(!d[i]) q.push(i);
	while(q.size()>1)
	{
		int u=q.front();q.pop();
		int v=q.front();q.pop();
		if(!ask(u,v)) swap(u,v);
		q.push(u);
		for(int x:to[v]) if(!--d[x])
			q.push(x);
	}
	printf("! %d\n",q.front());
}

标签:Pink,粉边,int,CF1142E,read,Floyd,管辖,front,include
来源: https://www.cnblogs.com/C202044zxy/p/16287298.html

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

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

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

ICode9版权所有