Strongly Connected Componenet
namespace Graph
{
const int __=2e5+5;
int n,v[__];//点权
vector<int>G[__];
void init(int _n)
{
n=_n;
for(int i=1;i<=n;++i)
G[i].clear();
}
void add_edge(int x,int y)//有向边
{
G[x].push_back(y);
}
}
namespace SCC
{
const int __=2e5+5;
vector<int>G[__];//缩点后注意重边有影响使用set
int n,idx,dfn[__],low[__],bel[__],s[__];//栈
ll v[__];//缩点后的点权
int dfs(int x)
{
if(dfn[x])return dfn[x];
s[++*s]=x;
dfn[x]=low[x]=++idx;
for(int y:Graph::G[x])
if(!bel[y])
low[x]=min(low[x],dfs(y));
if(low[x]==dfn[x])
for(bel[x]=++n,v[n]=0;;--*s)
{
v[n]+=Graph::v[s[*s]];
if(s[*s]==x){--*s;break;}
else bel[s[*s]]=n;
}
return low[x];
}
void tarjan()//注意一个点的特判
{
idx=n=*s=0;
for(int i=1;i<=Graph::n;++i)
if(!dfn[i])dfs(i);
for(int i=1;i<=Graph::n;++i)
for(int y:Graph::G[i])
if(bel[i]!=bel[y])
G[bel[i]].push_back(bel[y]);
}
void clear()
{
for(int i=1;i<=Graph::n;++i)
{
dfn[i]=bel[i]=0;
G[i].clear();
}
}
void print()
{
for(int i=1;i<=Graph::n;++i)
printf("bel[%d]=%d\n",i,bel[i]);
for(int i=1;i<=n;++i)
{
printf("%d:",i);
for(int x:G[i])
pf(" %d",x);
putchar('\n');
}
}
}
割点(tarjan):
vector<int>G[105];
int low[105],dfn[105],cut[105],cont=1,ans=0;
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
son++;
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if(low[nex]>=dfn[x]&&fa!=-1&&!cut[x])
{
cut[x]=1;
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1)
{
cut[x]=1;
ans++;
}
}
tarjan:
vector<int>G[105];
int low[105],dfn[105],cut[105],cont=1,ans=0;
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
son++;
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if(low[nex]>=dfn[x]&&fa!=-1&&!cut[x])
{
cut[x]=1;
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1)
{
cut[x]=1;
ans++;
}
}
void init(void)
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cut,0,sizeof(cut));
cont=1; ans=0;
}
int main()
{
int n,x,y;
char ch;
while(~scanf("%d",&n)&&n)
{
init();
while(~scanf("%d",&x)&&x)
while((ch=getchar())!='\n')
{
scanf("%d",&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1; i<=n; i++)
if(!dfn[i])dfs(-1,i);
printf("%d\n",ans);
for(int i=1; i<=n; i++)
G[i].clear();
}
return 0;
}
tarjan:
int low[100005],dfn[100005],cut[100005],cont=1,ans=0;
vector<int>G[100005];
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
son++;
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if(low[nex]>=dfn[x]&&fa!=-1&&!cut[x])
{
cut[x]=1;
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1)
{
cut[x]=1;
ans++;
}
}
int main()
{
int m,n,x,y;
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1; i<=n; i++)
if(!dfn[x])dfs(-1,i);
printf("%d\n",ans);
int res=0;
for(int i=1;i<=n;i++)
if(cut[i])
{
if(res!=0)printf(" ");
res=1;
printf("%d",i);
}
return 0;
}
割边(tarjan):
int low[100005],dfn[100005],cont,ans;
vector<int>G[100005];
vector<pair<int,int> >bri;
void dfs(int fa,int x)
{
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if(low[nex]>dfn[x])
{
if(nex>x)bri.push_back(make_pair(x,nex));
else bri.push_back(make_pair(nex,x));
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
}
tarjan:
int low[100005],dfn[100005],cont,ans;
vector<int>G[100005];
vector<pair<int,int> >bri;
void dfs(int fa,int x)
{
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if(low[nex]>dfn[x])
{
if(nex>x)bri.push_back(make_pair(x,nex));
else bri.push_back(make_pair(nex,x));
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
}
void init(void)
{
bri.clear();
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cont=1;
ans=0;
}
int main()
{
int T,n,x,y,m;
while(~scanf("%d",&T))
{
init();
n=T;
while(T--)
{
scanf("%d (%d)",&x,&m);
for(int i=0; i<m; i++)
{
scanf("%d",&y);
G[x+1].push_back(y+1);
G[y+1].push_back(x+1);
}
}
for(int i=1; i<=n; i++)
if(!dfn[i])dfs(-1,i);
printf("%d critical links\n",ans);
sort(bri.begin(),bri.end());
int len=bri.size();
for(int i=0;i<len;i++)
printf("%d - %d\n",bri[i].first-1,bri[i].second-1);
printf("\n");
for(int i=1;i<=n;i++)
G[i].clear();
}
return 0;
}
tarjan:
int low[20005],dfn[20005],cut[20005],cont,ans;
vector<int>G[20005];
vector<pair<int,int> >bri;
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
son++;
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if(low[nex]>dfn[x]) //桥
if(nex>x)bri.push_back(make_pair(x,nex));
else bri.push_back(make_pair(nex,x));
if(low[nex]>=dfn[x]&&fa!=-1&&!cut[x]) //割点
{
ans++;
cut[x]=1;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1) //根节点割点判定
{
cut[x]=1;
ans++;
}
}
void init(void)
{
bri.clear();
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cont=1;
ans=0;
}
int main()
{
int n,m,x,y;
init();
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1; i<=n; i++)
if(!dfn[i])dfs(-1,i);
sort(bri.begin(),bri.end());
bool flag=false;
if(ans==0)printf("Null\n");
else
for(int i=1; i<=n; i++)
if(cut[i])
{
if(flag)printf(" ");
printf("%d",i);
flag=true;
}
printf("\n");
int len=bri.size();
for(int i=0; i<len; i++)
printf("%d %d\n",bri[i].first,bri[i].second);
return 0;
}
强联通分量:
Kosaraju:
vector<int>G[10005]; //正向边
vector<int>Gr[10005]; //反向边
stack<int>S;
int vis[10005];
int m,n;
void dfs_normal(int node)
{
vis[node]=1;
int len=G[node].size();
for(int i=0; i<len; i++)
if(!vis[G[node][i]])dfs_normal(G[node][i]);
S.push(node);
}
void dfs_reverse(int node)
{
vis[node]=1;
int len=Gr[node].size();
for(int i=0; i<len; i++)
if(!vis[Gr[node][i]])dfs_reverse(Gr[node][i]);
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
if(m==0&&n==0)return 0;
int x,y;
for(int i=0; i<n; i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
Gr[y].push_back(x);
}
for(int i=1; i<=m; i++)
{
if(!vis[i])dfs_normal(i);
vis[i]=0;
}
int cont=0;
while(!S.empty())
{
int t=S.top();
S.pop();
if(!vis[t])
{
dfs_reverse(t);
cont++;
}
}
if(cont==1)printf("Yes\n");
else printf("No\n");
for(int i=1; i<=m; i++)
{
G[i].clear();
Gr[i].clear();
vis[i]=0;
}
}
return 0;
}
tarjan:
vector<int>G[50005];
int vis[50005];
int dfn[50005];
int low[50005];
int cont=1;
int n,m,ans=0;
stack<int>S;
void dfs(int x)
{
dfn[x]=low[x]=cont++;
S.push(x);vis[x]=1;
int len=G[x].size();
for(int i=0; i<len; i++)
if(!vis[G[x][i]])
{
dfs(G[x][i]);
low[x]=min(low[x],low[G[x][i]]);
}
else if(vis[G[x][i]]==1)
low[x]=min(low[x],dfn[G[x][i]]);
if(dfn[x]==low[x])
{
int res=0;
while(1)
{
int t=S.top();
S.pop();
vis[t]=2; //访问完成
res++;
if(x==t)break;
}
if(res>1)ans++;
}
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
for(int i=0; i<m; i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
}
for(int i=1; i<=n; i++)
if(!vis[i])dfs(i);
printf("%d\n",ans);
return 0;
}
双联通分量:
tarjan:
int low[20005],dfn[20005],cont,ans;
int bel[20005],minn[20005];
vector<int>G[20005];
stack<int>S;
void dfs(int fa,int x)
{
dfn[x]=low[x]=cont++;
S.push(x);
int len=G[x].size();
for(int i=0;i<len;i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(!dfn[nex])
{
dfs(x,nex);
low[x]=min(low[x],low[nex]);
}
else low[x]=min(low[x],dfn[nex]);
}
if(low[x]==dfn[x])
{
minn[++ans]=inf;
while(1)
{
int t=S.top();
S.pop();
minn[ans]=min(minn[ans],t);
bel[t]=ans;
if(t==x)break;
}
}
}
void init(void)
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(bel,0,sizeof(bel));
cont=1;
ans=0;
}
int main()
{
int n,m,x,y;
init();
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1;i<=n;i++)
if(!dfn[i])dfs(-1,i);
printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
printf("%d",minn[bel[i]]);
if(i!=n)printf(" ");
else printf("\n");
}
return 0;
}
tarjan:
struct node
{
int nex,id;
} t;
struct edge
{
int now,nex,id;
} temp;
int low[20005],dfn[20005],bel[100005],minn[100005],cont,ans;
bool vis[100005];
stack<edge>S;
vector<node>G[20005];
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i].nex;
int id=G[x][i].id;
if(nex==fa||vis[id])continue;
temp.id=id, temp.now=x, temp.nex=nex;
S.push(temp);
if(!dfn[nex])
{
son++;
dfs(x,nex);
low[x]=min(low[x],low[nex]);
if((low[nex]>=dfn[x]&&fa!=-1)||(son>1&&fa==-1))
{
ans++;
while(1)
{
temp=S.top();
S.pop();
bel[temp.id]=ans;
minn[ans]=min(minn[ans],temp.id);
vis[temp.id]=true;
if(temp.now==x&&temp.nex==nex)break;
}
}
}
else low[x]=min(low[x],dfn[nex]);
}
}
void init(int n)
{
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(bel,0,sizeof(bel));
memset(vis,false,sizeof(vis));
cont=1;
ans=0;
for(int i=1; i<=n; i++)
minn[i]=inf;
}
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
init(m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
t.id=i;
t.nex=y;
G[x].push_back(t);
t.nex=x;
G[y].push_back(t);
}
for(int i=1; i<=n; i++)
if(!dfn[i])dfs(-1,i);
ans++;
while(!S.empty())
{
temp=S.top();
S.pop();
bel[temp.id]=ans;
minn[ans]=min(minn[ans],temp.id);
}
printf("%d\n",ans);
for(int i=1; i<=m; i++)
printf("%d ",minn[bel[i]]);
return 0;
}
网友评论