700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > [CF1142E]Pink Floyd

[CF1142E]Pink Floyd

时间:2022-07-12 23:45:00

相关推荐

[CF1142E]Pink Floyd

Description

这是一道交互题

有一张n个点的竞赛图,其中有m条边为粉红色,另外的边为绿色

你现在只知道这m条边的方向,你每次可以询问交互库某条绿边的方向

你需要用不超过2n次询问找到一个点x,使得对于其余所有点y,存在一条x到y的颜色相同的路径

n,m<=10^5

Solution

先考虑没有粉色怎么做,这个很简单,直接维护当前的关键点x,对于每个点y询问(x,y),如果是x->y保留x否则将关键点设为y

有粉色的话我们可以先对于粉图做一遍dfs,找到粉图中的关键点

然后我们需要用绿边把粉图中的所有关键点连起来,这个可以用上面的做法

注意我们要求的路径是同色的,所以当一个关键点被绿边连接之后它就会在粉图中被删除,这时候要重新维护所有的关键点

因为每次询问都会删除一个点,所以询问次数最多为n-1

Code

#include <vector>#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define pb(a) push_back(a)using namespace std;int read() {char ch;for(ch=getchar();ch<'0'||ch>'9';ch=getchar());int x=ch-'0';for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';return x;}int query(int u,int v) {printf("? %d %d\n",u,v);fflush(stdout);return read();}void answer(int v) {printf("! %d\n",v);fflush(stdout);}const int N=1e5+5;int n,m,deg[N],q[N];vector<int> to[N],e[N];bool vis[N],in[N];void dfs(int x) {vis[x]=in[x]=1;for(int z:to[x]) {if (!in[z]) e[x].pb(z),deg[z]++;if (!vis[z]) dfs(z);}in[x]=0;}int main() {n=read();m=read();fo(i,1,m) {int u=read(),v=read();to[u].pb(v);}fo(i,1,n) if (!vis[i]) dfs(i);fo(i,1,n) if (!deg[i]) q[++q[0]]=i;for(;q[0]>1;) {int u=q[q[0]--],v=q[q[0]--];if (!query(u,v)) swap(u,v);q[++q[0]]=u;for(int z:e[v]) if (!(--deg[z])) q[++q[0]]=z;}answer(q[1]);return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。