[Tarjan] BZOJ5201: [NEERC2017]Connections

tarjan的时候每次每次加入一条返祖边,都会至少缩去一个点,那么只要记录一下遍历过的边以及返祖边就可以了

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

const int N=100010;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

int T,n,m,cnt,G[N],dfn[N],low[N],S[N],vis[N],tk[N],tcnt,top,t;
struct edge{
  int s,t,nx;
}E[N];

inline void addedge(int x,int y){
  E[++cnt].t=y; E[cnt].s=x; E[cnt].nx=G[x]; G[x]=cnt;
}

void dfs(int x){
  dfn[x]=low[x]=++t; vis[x]=1;
  S[++top]=x; int bck=0;
  for(int i=G[x];i;i=E[i].nx){
    if(!vis[E[i].t]){
      dfs(E[i].t),low[x]=min(low[x],low[E[i].t]);
      tk[i]=1,tcnt++;
    }
    if(vis[E[i].t]!=2){
      if(low[E[i].t]<low[x])
    low[x]=low[E[i].t],bck=i;
    }
  }
  if(bck) tk[bck]=1,tcnt++;
  if(low[x]==dfn[x]){
    int u;
    do{
      u=S[top--]; vis[u]=2;
    }while(u!=x && top);
  }
}

int main(){
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  read(T);
  while(T--){
    read(n); read(m);
    for(int i=1,x,y;i<=m;i++)
      read(x),read(y),addedge(x,y);
    dfs(1);
    for(int i=1;i<=m && tcnt<2*n;i++)
      if(!tk[i]){
    tk[i]=1; tcnt++;
      }
    for(int i=1;i<=m;i++) if(!tk[i]) printf("%d %d\n",E[i].s,E[i].t);
    cnt=t=top=tcnt=0;
    for(int i=1;i<=n;i++) G[i]=dfn[i]=low[i]=vis[i]=0;
    for(int i=1;i<=m;i++) tk[i]=0;
  }
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页