NOIp模拟赛 现实(DP 拓扑)
题目来源:by lzz
\(Description\)
给定一张有向图,求对于哪些点,删除它和它的所有连边后,图没有环。
\(n\leq 5\times10^5,m\leq 10^6\)。
\(Solution\)
题目等价于求所有环的交集。
首先两个特判:如果原图没有环,输出所有点;如果删掉原图的某个环后,仍存在环,输出\(0\)。这也是不少分了。
先求出图中的某个环,环交当然在这个环上。我们只需要处理这个环。
把环拆成链,发现所有除它外的环只有两种情况:
对于第一种情况,
如果做过这个链的Subtask,很容易发现(倒也显然)合法的点只可能是这些环的交集(把红边看成线段,就是求区间的交)。之前的第二次判环可以拓扑,然后利用拓扑序从出度为0的点更新能到它的点的最左位置\(pl\)、从入度为0的点更新它到的点的最右位置\(pr\)。然后就可以找到最右的左端点和最靠左的右端点。
对于第二种情况,
显然,如果存在红边\(x\rightarrow y\),则\(x,y\)之间的点都不是合法的。
依旧利用拓扑序从出度为0的点更新到它的点的最右位置\(pr\),然后扫一遍。
两种情况都合法的点就是答案了。
发现图中只有两个环,且环交为1个点时,这个点是合法的,但是删掉环边后图仍存在环,会返回无解。我们发现如果将每个点拆成入点和出点,这种情况就可以处理了。即把环交从点集变成边集。
复杂度\(O(n+m)\)。
#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=1e6+5,M=1e6+5+N;
int n,m,Enum,H[N],nxt[M],to[M],dgr[N],cir[N],sz,pre[N],fa[N],q[N],pl[N],pr[N];
bool find_circle,vis[N],ins[N],isc[M],ok[N];
std::vector<int> ans;
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AE(int v,int u)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
}
void DFS(int x)
{
vis[x]=ins[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]])
{
fa[v]=x, pre[v]=i, DFS(v);
if(find_circle) return;
}
else if(ins[v])
{
for(int p=x; p!=v; p=fa[p]) cir[++sz]=p, isc[pre[p]]=1;
cir[++sz]=v, isc[i]=1;
std::reverse(cir+1,cir+1+sz);
find_circle=1; return;
}
ins[x]=0;
}
bool Toposort()
{
int h=0,t=0;
for(int i=1; i<=Enum; ++i) if(!isc[i]) ++dgr[to[i]];//度也是删环后的!
for(int i=1; i<=n; ++i) if(!dgr[i]) q[t++]=i;
while(h<t)
{
int x=q[h++];
for(int i=H[x]; i; i=nxt[i])
if(!isc[i] && !--dgr[to[i]]) q[t++]=to[i];
}
return t==n;
}
void Solve()
{
for(int i=1; i<=n; ++i)
if(!vis[i]) {DFS(i); if(find_circle) break;}
if(!find_circle)
{
n>>=1;
for(int i=1; i<=n; ++i) ans.push_back(i);
return;
}
if(!Toposort()) return;
int ansl=1,ansr=sz;
for(int i=1; i<=sz; ++i) pl[cir[i]]=pr[cir[i]]=i;
for(int i=n,x; i; --i)
{
if(!pl[x=q[i]]) pl[x]=N;//避免环外的影响
for(int j=H[x]; j; j=nxt[j])
if(!isc[j]/*!*/) pl[x]=std::min(pl[x],pl[to[j]]);//非环边!又忘判了
}
for(int i=1; i<=sz; ++i)
if(pl[cir[i]]<i) {ansr=i; break;}//对于左端端点应该有pl[i]==i
for(int i=1,x; i<=n; ++i)
{
// if(!pr[x=q[i]]) pr[x]=0;
for(int j=H[x=q[i]]; j; j=nxt[j])
if(!isc[j]) pr[to[j]]=std::max(pr[to[j]],pr[x]);
}
for(int i=sz; i; --i)
if(pr[cir[i]]>i) {ansl=i; break;}
if(ansl>ansr) return;
memset(pr,0,sizeof pr);
for(int i=1; i<=sz; ++i) pr[cir[i]]=i;
for(int i=n,x; i; --i)//对另一个方向的pr再求一次
{
// if(!pr[x=q[i]]) pr[x]=0;
for(int j=H[x=q[i]]; j; j=nxt[j])
if(!isc[j]) pr[x]=std::max(pr[x],pr[to[j]]);
}
int nowr=0;
for(int i=1; i<=sz; ++i)
{
if(i>=nowr) ok[i]=1;
nowr=std::max(nowr,pr[cir[i]]);
}
for(int i=ansl; i<ansr; i+=2) if(ok[i]) ans.push_back(cir[i]);//ansl一定是个入点
std::sort(ans.begin(),ans.end());
}
int main()
{
n=read();
for(int i=1; i<=n; ++i) AE(i+n,i);//in:x out:x+n 参数顺序!
for(int m=read(); m--; AE(read(),read()+n));
n<<=1, Solve();
printf("%d\n",ans.size());
for(int i=0,l=ans.size(); i<l; ++i) printf("%d ",ans[i]);
return 0;
}
NOIp模拟赛 现实(DP 拓扑)的更多相关文章
- 放棋游戏(NOIP模拟赛)(DP)
没有原题... 囧.. [问题描述] 游戏规则是这样,有n(1<=n<=100)行格子,第一行由n个格子,第二行有n-1个格子,第三行由n-2个格子,……以此类推,第n行有1个格子.要求再 ...
- 【noip模拟赛5】细菌 状压dp
[noip模拟赛5]细菌 描述 近期,农场出现了D(1<=D<=15)种细菌.John要从他的 N(1<=N<=1,000)头奶牛中尽可能多地选些产奶.但是如果选中的奶牛携 ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
- 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- CH Round #52 - Thinking Bear #1 (NOIP模拟赛)
A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...
随机推荐
- BackBone结合ASP.NET MVC实现页面路由操作
1. 问题的背景 什么是页面路由操作,就是通过浏览器地址栏的标记来实现页面内部的一些操作,这些操作具有异步性和持久性.应用场景主要有页面操作过程中的添加收藏夹的操作.后退操作等过程中能完全恢复界面. ...
- 【windows核心编程】注入DLL时BUG排除与调试
DLL注入排除bug的思路步骤. 1.在VS中监视输入err,hr检查DLL是否注入成功 2.OD断点loadlibraryW,loadlibraryA是否已经注入成功,eax是否有值. 3.检查路径 ...
- linux内核capable源代码分析【转】
转自:https://blog.csdn.net/sanwenyublog/article/details/50856849 linux内核里对于进程的权限管理有一个很重要的函数capable,以前看 ...
- HTML学习笔记09-列表
HTML支持无序,有序,自定义列表 列表项内部可以使用段落.换行符.图片.连接.以及其他列表等 无序列表 无序列表使用粗体圆点(典型的小黑圆圈)进行标记,列表始于<ul>标签,列表项使用& ...
- abstract class 和 interface 区别
本文出自与:heipai:tsg666 含有 abstract 修饰符的 class 即为抽象类,abstract 类不能创建的实例对象.含有 abstract 方法的类必须定义为 abstract ...
- v-bind绑定属性样式——class的三种绑定方式
1.布尔值的绑定方式 <div id="demo"> <span v-bind:class="{‘class-a‘:isA ,‘class-b‘:isB ...
- python 全栈开发,Day97(Token 认证的来龙去脉,DRF认证,DRF权限,DRF节流)
昨日内容回顾 1. 五个葫芦娃和三行代码 APIView(views.View) 1. 封装了Django的request - request.query_params --> 取URL中的参数 ...
- python 全栈开发,Day52(关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列)
昨日作业讲解: 京东购物车 京东购物车效果: 实现原理: 用2个盒子,就可以完整效果. 先让上面的小盒子向下移动1px,此时就出现了压盖效果.小盒子设置z-index压盖大盒子,将小盒子的下边框去掉, ...
- python 全栈开发,Day28(复习,os模块,导入模块import和from)
一.复习 collections 增加了一些扩展数据类型 :namedtuple orderdict defaltdict队列和栈time 时间 三种格式 : 时间戳 结构化 字符串random 随机 ...
- python 全栈开发,Day8(文件操作)
一.文件操作流程 文件以什么编码存储的,就以什么编码打开 参数: 1.文件路径 2.编码方式,encode 3.执行动作(打开方式):只读,只写,追加,读写,写读... 打开一个已经存在的文件 f = ...