tarjan 算法模板(边连通分量)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#define M 50005
#define SZ(x) x.size()
#define FF(x,xi,y) for(int x=xi;x<=y;++x)
#define FFL(x,u) for(int x=head[u];x!=-1;x=edge[x].next)
#define CC(x,y) memset(x,y,sizeof(x))
using namespace std;
int tot,head[M],ncase,newhead[M],id[M],pre[M],low[M],n,m,nn,hash[M],top,index,stack[M];
struct pp{int v,next;}edge[5*M];
inline void addedge(int u,int v){edge[tot].v=v,edge[tot].next=head[u],head[u]=tot++;}
inline void addnewedge(int u,int v){edge[tot].v=v,edge[tot].next=newhead[u],newhead[u]=tot++;}
template<class T> inline void checkmax(T &x,T y){if(x<y) x=y;}
template<class T> inline void checkmin(T &x,T y){if(x>y) x=y;}
template<class T> inline T Min(T x,T y){return (x>y?y:x);}
template<class T> inline T Max(T x,T y){return (x<y?y:x);}
void dfs(int r)
{
pre[r]=low[r]=index++;
stack[++top]=r;
FFL(i,r)
{
if(pre[edge[i].v]==-1)
{
dfs(edge[i].v);
checkmin(low[r],low[edge[i].v]);
}
else
if(id[edge[i].v]==-1)
checkmin(low[r],pre[edge[i].v]);
}
if(pre[r]==low[r])
{
int v=0;
while(r!=v)
{
if(v==-1) break;
v=stack[top--];
id[v]=nn;
}
newhead[nn++] = -1;
}
}
void tarian()
{
CC(pre,-1);
CC(hash,-1);
CC(id,-1);
stack[0]=-1;
index=0,top=0,nn=1;
FF(i,1,n){if(pre[i]==-1) dfs(i); }
FF(i,1,n)
{
FFL(j,i)
{
int v=edge[j].v;
if(id[v]!=id[i]&&hash[id[i]]!=id[v])
{ hash[id[i]]=id[v];
addnewedge(id[i],id[v]);
}
}
}
}
int main()
{
scanf("%d",&ncase);
while(ncase--)
{
CC(head,-1);
scanf("%d%d",&n,&m);
tot=0;
FF(i,1,m){int u,v;scanf("%d%d",&u,&v); addedge(u,v);}
tarian();
int ind[M]={},od[M]={};
FF(i,1,nn-1)
{
for(int j=newhead[i];j!=-1;j=edge[j].next)
ind[edge[j].v]++,od[i]++;
}
int maxi=0,maxo=0;
FF(i,1,nn-1) {if(ind[i]==0) maxi++;if(od[i]==0) maxo++;}
printf("%d\n",nn==2?0:Max(maxi,maxo));
}
return 0;
}

你可能感兴趣的:(算法,struct)