版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/86510200
传送门
解析:
为什么这道题卡了我50多分钟?
因为STL。。。
我也不知道为什么,我把vector换成了stack后,减少了每次init清空vector的常数。
然后我就从被卡常变成了跑得飞快?
思路:
这道题要求哪些边能够在以 开头的简单路径中出现。
可以,这很不支配树。
所以我们好好想想这个限制怎么转化。
发现对于一个边 就是要求我们能够在到达 之前到达 ,就能够让这条边在简单路径中出现。
所以就是 不可以是 的必经点,用支配树上的话来说就是 不在 的子树中。
构建支配树,然后构建 序,枚举每条边判断。然后就没了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<20|1;
char buf[Rlen],*p1,*p2;
char obuf[Rlen],*p3=obuf;
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline void put_char(char c){
using namespace IOONLY;
*p3++=c;
if(p3==obuf+Rlen)fwrite(obuf,1,Rlen,stdout),p3=obuf;
}
inline void FLUSH(){
using namespace IOONLY;
fwrite(obuf,1,p3-obuf,stdout),p3=obuf;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()))if(c==EOF)return EOF;re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline void outint(int a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
}
using namespace IO;
cs int N=200005;
int n,m;
struct Graph{
vector<int> edge[N];
inline void clear(){for(int re i=1;i<=n;++i)edge[i].clear();}
inline void addedge(int u,int v){edge[u].push_back(v);}
}g,revg,dt;
stack<int> dom[N];
struct E{int u,v;}e[N];
int fa[N],dfn[N],id[N],dfs_clock;
void dfs(int u){
id[dfn[u]=++dfs_clock]=u;
for(int re e=0,v;e<g.edge[u].size();++e){
v=g.edge[u][e];
if(dfn[v])continue;
fa[v]=u;dfs(v);
}
}
int bel[N],val[N],semi[N],idom[N];
inline int getfa(int x){
if(bel[x]==x)return x;
int tmp=getfa(bel[x]);
if(dfn[semi[val[bel[x]]]]<dfn[semi[val[x]]])val[x]=val[bel[x]];
return bel[x]=tmp;
}
inline void tarjan(){
for(int re i=dfs_clock;i>1;--i){
int u=id[i];
for(int re e=0,v;e<revg.edge[u].size();++e){
v=revg.edge[u][e];
if(!dfn[v])continue;
getfa(v);
if(dfn[semi[val[v]]]<dfn[semi[u]])semi[u]=semi[val[v]];
}
dom[semi[u]].push(u);
u=bel[u]=fa[u];
while(dom[u].size()){
int v=dom[u].top();dom[u].pop();
getfa(v);
if(semi[val[v]]==u)idom[v]=u;
else idom[v]=val[v];
}
}
for(int re i=2;i<=dfs_clock;++i){
int u=id[i];
if(idom[u]!=semi[u])idom[u]=idom[idom[u]];
dt.addedge(idom[u],u);
}
}
int dt_in[N],dt_out[N],dt_clock;
void dfs_dt(int u){
dt_in[u]=++dt_clock;
for(int re e=0,v;e<dt.edge[u].size();++e){
v=dt.edge[u][e];
dfs_dt(v);
}
dt_out[u]=dt_clock;
}
vector<int> ans;
void init(){
g.clear();
revg.clear();
dt.clear();
for(int re i=1;i<=n;++i)semi[i]=bel[i]=val[i]=i,dfn[i]=0;
dfs_clock=dt_clock=0;
ans.clear();
}
signed main(){
while(~(n=getint())){
init();
m=getint();
for(int re i=1;i<=m;++i){
e[i].u=getint(),e[i].v=getint();
g.addedge(e[i].u,e[i].v);
revg.addedge(e[i].v,e[i].u);
}
dfs(1);
tarjan();
dfs_dt(1);
for(int re i=1;i<=m;++i){
int u=e[i].u,v=e[i].v;
if(!dfn[u]||!dfn[v])continue;
if(dt_in[v]<=dt_in[u]&&dt_in[u]<=dt_out[v])continue;
else ans.push_back(i);
}
outint(ans.size());pc('\n');
for(int re i=0;i<ans.size();++i)outint(ans[i]),pc(' ');
pc('\n');
}
FLUSH();
return 0;
}