显然我们先缩点,之后转化为一个 DAG,设为 GGG,设由其反边构成的图为 G′G'G′。题意就是求所有 “好的” 点,其中一个 “好的” 点需要满足这个点在 GGG 上能走到的点和在 G′G'G′ 上能走到的点的并集为所有点。

思路 1:显然一个点不可能同时在 GGG 和 G′G'G′ 上都能被同一个点 uuu 走到(除了这个点就是 uuu),于是我们可以在 GGG 和 G′G'G′ 上分别求出 uuu 能走到的点的个数,再加起来判断是否等于 n+1n+1n+1。但你发现这个能走到的点的个数并不好快速求。(如果用 bitset+拓扑 那么与直接暴力无异)

我们可以将限制改的更严一点:我们先对 GGG 随便跑一个拓扑序出来,假设点 uuu 的拓扑序为 aua_uau​。那么一个点 uuu 如果是 “好的” 点,当且仅当:在 GGG 上,拓扑序比 uuu 小的点都能走到 uuu,拓扑序比 uuu 大的点 uuu 都能走到。

思路 2:注意到这个条件其实告诉了我们一个隐含的信息:某个 “好的” 点 uuu 一定满足 uuu 在拓扑序的位置唯一。但是在考场上并没有想出来按这个思路做应该怎么做。

我们还是回到原来的要求:一个点 uuu 如果是 “好的” 点,当且仅当:在 GGG 上,拓扑序比 uuu 小的点都能走到 uuu,拓扑序比 uuu 大的点 uuu 都能走到。

对于一个点 uuu,我们可以先考虑哪些点 uuu 走不到,那么 uuu 走不到的点肯定不是 “好的” 点。我们可以找出 uuu 的所有儿子中拓扑序最小的那个点 vvv,那么拓扑序在 (au,av)(a_u,a_v)(au​,av​) 之间的点 uuu 肯定走不到,那么我们对区间 (au,av)(a_u,a_v)(au​,av​) 打上标记。

我们可以同样考虑哪些点走不到 uuu。

最后可以证明没有被打上标记的点一定是 ”好的“ 点。

#include<bits/stdc++.h>#define N 1000010using namespace std;inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^'0');ch=getchar();}return x*f;
}int n,m;
int cnt=1,head[N],nxt[N<<1],to[N<<1];
int idx,dfn[N],low[N];
int top,sta[N];
int nscc,scc[N];
int num,du[N],a[N];
int c[N];
bool ins[N];
bool cor[N];
bool F;vector<int>e[N];void tarjan(int u)
{dfn[u]=low[u]=++idx;sta[++top]=u,ins[u]=1;for(int v:e[u]){if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(ins[v]) low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){nscc++;int v;do{v=sta[top],top--;ins[v]=0;scc[v]=nscc;}while(v!=u);}
}void adde(int u,int v)
{to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}queue<int>q;void tuopu()
{num=0;for(int i=1;i<=nscc;i++)if(!du[i]) q.push(i);    while(!q.empty()){int u=q.front();q.pop();a[u]=++num;for(int i=head[u];i;i=nxt[i]){if((i&1)^F) continue;int v=to[i];du[v]--;if(!du[v]) q.push(v);}}
}void work()
{for(int i=1;i<=nscc;i++) du[i]=0;for(int i=2+F;i<=cnt;i+=2) du[to[i]]++;tuopu();if(num!=nscc){puts("0");exit(0);}for(int i=1;i<=nscc;i++) c[i]=0;for(int u=1;u<=nscc;u++){int minv=0;for(int i=head[u];i;i=nxt[i]){if((i&1)^F) continue;if(!minv||a[to[i]]<a[minv]) minv=to[i];}if(minv) c[a[u]+1]++,c[a[minv]]--;else c[a[u]+1]++,c[nscc+1]--;int maxv=0;for(int i=head[u];i;i=nxt[i]){if(!((i&1)^F)) continue;if(!maxv||a[to[i]]>a[maxv]) maxv=to[i];}if(maxv) c[a[maxv]+1]++,c[a[u]]--;else c[1]++,c[a[u]]--;}for(int i=1;i<=nscc;i++) c[i]+=c[i-1];for(int i=1;i<=nscc;i++) if(c[a[i]]) cor[i]=0;
}int main()
{n=read(),m=read();for(int i=1;i<=m;i++){int u=read(),v=read();e[u].push_back(v);}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for(int u=1;u<=n;u++){for(int v:e[u]){if(scc[u]!=scc[v]){adde(scc[u],scc[v]);adde(scc[v],scc[u]);}}}for(int i=1;i<=nscc;i++) cor[i]=1;F=0;work();vector<int>ans;ans.clear();for(int i=1;i<=n;i++)if(cor[scc[i]]) ans.push_back(i);printf("%d\n",(int)ans.size());for(int u:ans) printf("%d ",u);return 0;
}
/*
6 7
1 2
1 3
2 4
3 4
4 5
5 6
6 5
*/

【XSY3325】社保(拓扑序)相关推荐

  1. 解题报告:NOIP2013 车站分级(拓扑序递推求解差分约束、建图优化O(n+m)) 超详细讲解

    本题是2013年NOIP普及组的压轴题 差分约束裸题. 计算当前线路中最小的级别(比较始发站和终点站). 整条线路中所有大于这个级别的都必须停靠 所有未停靠的站点的级别一定小于这个级别 也就是说所有未 ...

  2. hdu3342 拓扑序

    题意:一个QQ群里面有一群大神,他们互相帮助解决问题,然后互相膜拜,于是有些人就称别人是他师父,现在给出很多师徒关系,问是否有矛盾 拓扑序,按师徒关系建边直接拓扑序就行了. 1 #include< ...

  3. BZOJ3832 [Poi2014]Rally 【拓扑序 + 堆】

    题目链接 BZOJ3832 题解 神思路orz,根本不会做 设\(f[i]\)为到\(i\)的最长路,\(g[i]\)为\(i\)出发的最长路,二者可以拓扑序后\(dp\)求得 那么一条边\((u,v ...

  4. Weights Assignment For Tree Edges 树,拓扑序(1500)

    题意 : 给定n个结点的树和序列bbb和ppp,bib_ibi​表示i结点的父节点,其中broot=rootb_{root}=rootbroot​=root,现在要给树上的每个边赋正权值,使得每个结点 ...

  5. 字典序最小是什么意思_《拓扑序简介》第十六讲

    这是民科+大忽悠+地摊报告,我准备把拓扑序吹成天上有地上无.人见人爱.老幼咸宜.不买会后悔的什么东西.珍惜青春,珍惜钱包,请大家谨慎对待大忽悠.下面是回放视频的链接. 蔻享--共享科学.传播科学​ww ...

  6. CF1385E Directing Edges 拓扑序

    传送门 文章目录 题意: 思路: 题意: 给你一个图和若干个边,有些是有向边,有些是无向边,让你给无向边定向,使得最终的图是DAGDAGDAG. 思路: 题目让构造DAGDAGDAG,比较容易想到拓扑 ...

  7. HDU - 1811 Rank of Tetris 并查集 + 拓扑序 +me

    link 题意: 首先看到排名自然想到拓扑序,但是存在等于的情况,这就启发我们把等于的情况缩成一个点,让后在缩点后的图中进行拓扑即可. 对于不合法的情况当然是拓扑序没有遍历到应该遍历的点,所以只需要检 ...

  8. 【图论训练】最小拓扑序

    最小拓扑序 topsort.pas/c/cpp [题目描述] 给一个有向无环图,求其字典序最小的拓扑序. 一个拓扑序被认为字典序{pi}最小当且仅当对于任何其他拓扑序{qi},均存在正整数k,使得对于 ...

  9. hihocoder 1457 : 后缀自动机四·重复旋律7(后缀自动机+拓扑序BFS)

    #1457 : 后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成 ...

最新文章

  1. android studio数据库存储数据,如何使用API​​ 23在android studio中的数据库中存储数据?...
  2. 烂泥:nginx同时支持asp.net与php
  3. 一、Java入门和环境安装
  4. 算法之动态规划——编辑距离问题
  5. Java中proc是什么意思,在java里头读取/proc/net/dev
  6. arcgis 属性表 汇总_Arcgis中遥感影像地理配准、矢量化与地图制作
  7. 未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral,解决
  8. 恢复rm删除的文件(ext3
  9. AquaFold.Data.Studio.v6.5
  10. Linux下如何使用gcc编译器,Linux下gcc编译器的使用总结
  11. 毕业设计~在线教育系统
  12. c语言清屏函数怎么用_怎么用好 Golang 的 init 函数
  13. Java输入/输出流
  14. 行为树 中断的理解
  15. matlab中readfid函数,matlab中textscan和textread函数的比较使用
  16. WEB:Wife_wife
  17. 网络协议栈TSO/UFO/GSO/LRO/GRO/RSS特性
  18. 【Linux】Linux下安装gcc/g++
  19. Python文件和数据格式化学习笔记
  20. 图解华为云需求管理工具——CodeArts Req

热门文章

  1. linux 查找后删除目录,linux中find与rm实现查找并删除目录或文件
  2. C语言调试教程总结(以visual studio和Dev C++为例)
  3. 【高级篇 / DNS】(7.0) ❀ 03. FortiGate作为Window DNS的备用DNS服务器 ❀ FortiGate 防火墙
  4. 怎样在PDF文档中添加插入图片
  5. 浏览器证书失效问题解决方法
  6. 计算机组成原理笔记——机器指令
  7. Inventory文件扩展
  8. ECCV 2020 论文大盘点-目标跟踪篇
  9. 【Word】Word运行时提示“Word在试图打开文件时遇到错误”的解决办法
  10. c语言编程等边三角形代码,C语言中 正 倒等边三角形的代码