Tarjan求强连通分量的流程在这个博客讲的很清楚,再加上我也没理解透,这里就不写了。

缩点:将同一个连通块内的点视为同一个点。

扔一道模板题:codeVS2822爱在心中

第一问很显然就是求点数大于一的连通块的个数,跑一次tarjan;

第二问脑补一下发现,缩点后,若图中有且仅有一个点出度为0且为爱心天使,则该点为所求的特殊爱心天使;

因为当缩点之后,图中不存在环,若有且仅有一个爱心天使出度为0,那么其他点一定有通向该爱心天使的路径。

若有两个点出度为0,那么他们彼此不被对方所爱。

若没有点出度为0,则图中存在环,矛盾。

看起来似乎没什么问题,但是写出来第五个点挂掉了,代码查不出错,若有人看到这篇博客,希望在下方指出错误,谢谢。

 #include<cstdio>
#include<stack>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std; struct edge{
int to,next;
}; int a[][],dfn[],low[],head[],i,j,n,m,x,y,tag,ans[];
int ans1=,head2[],out[];
bool visited[],b[],lowb[];
edge e[],e2[];
stack<int> s; void tarjan(int k){
int i,v;
dfn[k]=low[k]=++tag;
b[k]=true;
s.push(k);
for(i=head[k];i!=-;i=e[i].next){
v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[k]=min(low[k],low[v]);
}else
if(b[v])
low[k]=min(low[k],dfn[v]);
}
int tmp=;
if(dfn[k]==low[k]){
//++ans1;
do{
v=s.top();
s.pop();
b[v]=false;
tmp++;
}while(v!=k);
if(tmp>=)++ans1;
}
} int ne=;
void add(int a,int b){
e[++ne].to=b; e[ne].next=head[a]; head[a]=ne;
} void add2(int a,int b){
e2[++ne].to=b; e2[ne].next=head2[a]; head2[a]=ne;
} int main(){
memset(head,-,sizeof(head));
memset(head2,-,sizeof(head2));
scanf("%d%d",&n,&m);
for(i=;i<=m;i++){
scanf("%d%d",&x,&y);
add(x,y);
}
tag=;
memset(dfn,,sizeof(dfn));
for(i=;i<=n;i++){
if(!dfn[i])tarjan(i);
}
printf("%d\n",ans1); ne=;
int n2=; for(i=;i<=n;i++){
if(!lowb[low[i]]){
n2=max(n2,low[i]);
lowb[low[i]]=true;//记录缩点后图中节点的编号
}
a[low[i]][++a[low[i]][]]=i;
for(j=head[i];j!=-;j=e[j].next){
int v=e[j].to;
if(low[i]!=low[v])
add2(low[i],low[v]);
}
//缩点:将low[]值相等的点看做一个点
} for(i=;i<=n2;i++){
if(!lowb[i])continue;
for(j=head2[i];j!=-;j=e2[j].next)
out[i]++;
} int sum=;
for(i=;i<=n2;i++){
if(out[i]==&&lowb[i]){
sum++;
j=i;
};
} if(sum!=||a[j][]<=){
printf("%d\n",-);
return ;
} for(i=;i<=a[j][];i++)
ans[i]=a[j][i]; sort(ans+,ans++a[j][]); for(i=;i<=a[j][];i++)
printf("%d ",ans[i]); printf("\n");
return ;
}

16.11.18:换了一种写法A了,然而还是不知道原来的代码有什么问题;

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
struct edge{int to,next;}e1[],e2[];
int head1[],head2[],dfn[],low[],belong[],out[];
bool instack[];
stack<int> s;
int dep,ne1,ne2,ans1,n,m,co;
void add1(int a,int b){
e1[++ne1].to=b;e1[ne1].next=head1[a];head1[a]=ne1;
}
void add2(int a,int b){
e2[++ne2].to=b;e2[ne2].next=head2[a];head2[a]=ne2;
}
void tarjan(int k){
dfn[k]=low[k]=++dep;
instack[k]=true;
s.push(k);
for(int i=head1[k];i!=-;i=e1[i].next){
int v=e1[i].to;
if(!dfn[v]){
tarjan(v);
low[k]=min(low[k],low[v]);
}
else if(instack[v])
low[k]=min(low[k],dfn[v]);
}
int t;
if(low[k]==dfn[k]){
int tmp=;
++co;
do{
t=s.top();
s.pop();
instack[t]=false;
belong[t]=co;//染色缩点
tmp++;
}while(t!=k);
if(tmp>)++ans1;
}
} int main(){
memset(head1,-,sizeof(head1));
memset(head2,-,sizeof(head2));
int i,j,u,v;
scanf("%d%d",&n,&m);
for(i=;i<=m;i++){
scanf("%d%d",&u,&v);
add1(u,v);
}
for(i=;i<=n;i++){
if(!dfn[i])tarjan(i);
}
printf("%d\n",ans1); int sum=,ang=;
for(i=;i<=n;i++){
for(j=head1[i];j!=-;j=e1[j].next){
int v=e1[j].to;
if(belong[v]!=belong[i]){
out[belong[i]]++;//若邻接的两点颜色不同,则出度加一。
}
}
}
for(i=;i<=co;i++){
if(out[i]==){
ang=i;
++sum;
}
}
if(sum==){
int sum2=;
for(i=;i<=n;i++){
if(belong[i]==ang)sum2++;
}
if(sum2>){
for(i=;i<=n;i++){
if(belong[i]==ang)printf("%d ",i);
}
printf("\n");
}else{printf("-1\n");return ;}
return ;
}
printf("-1\n");return ;
}

Tarjan模板——求强连通分量的更多相关文章

  1. Tarjan 算法求 LCA / Tarjan 算法求强连通分量

    [时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...

  2. HDU 1269 迷宫城堡 tarjan算法求强连通分量

    基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...

  3. [学习笔记] Tarjan算法求强连通分量

    今天,我们要探讨的就是--Tarjan算法. Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题. 首 ...

  4. 【算法】Tarjan算法求强连通分量

    概念: 在有向图G中,如果两个定点u可以到达v,并且v也可以到达u,那么我们称这两个定点强连通. 如果有向图G的任意两个顶点都是强连通的,那么我们称G是一个强连通图. 一个有向图中的最大强连通子图,称 ...

  5. tarjan算法求强连通分量

    先上代码: #include <iostream> #include <cstring> #include <vector> #include <stack& ...

  6. HDU1269迷宫城堡(裸Tarjan有向图求强连通分量个数)

    迷宫城堡Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  7. tarjan 算法求强连通分量

    #include<bits/stdc++.h> #define ll long long using namespace std; const int P=1e6; ; ; const i ...

  8. Tarjan求强连通分量、求桥和割点模板

    Tarjan 求强连通分量模板.参考博客 #include<stdio.h> #include<stack> #include<algorithm> using n ...

  9. 求强连通分量模板(tarjan算法)

    关于如何求强连通分量的知识请戳 https://www.byvoid.com/blog/scc-tarjan/ void DFS(int x) { dfn[x]=lowlink[x]=++dfn_cl ...

随机推荐

  1. es和数据库关系对比

    es类比传统关系型数据库:   Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -& ...

  2. tf调试函数

    Tensorflow之调试(Debug)及打印变量   参考资料:https://wookayin.github.io/tensorflow-talk-debugging 几种常用方法: 1.通过Se ...

  3. Linux--Centos7开机启动 mysql5.7.19

    参考:http://www.cnblogs.com/Anker/p/3551508.html

  4. Maven--mirror 和 repository

    参考:http://blog.csdn.net/isea533/article/details/22437511   http://www.cnblogs.com/xdouby/p/6502925.h ...

  5. Dynamics CRM - 如何创建一个新的 Organization

    最近需要新建几个 CRM 的场来测试或者开发,也就是要新建 Organization,但是每次我都忘了在哪操作,写篇 blog mark 一下. 首先,新建 Organization 当然是要在 CR ...

  6. Python说文解字_杂谈02

    1. Py中三个中啊哟的概念type.object和class的关系. type生成了int生成了1 type->class->obj type用来生成类对象的 object是最顶层的基类 ...

  7. c语言的各种技巧

    一.参考网址 1.参考网址1:C 语言的奇技淫巧 二.

  8. 后端Springboot前端VUE实现Excel导入功能

    功能描述:做的是物联网的项目,Excel导入实现的功能是将Excel中的数据批量的导入AEP系统,再导入我们系统中.目前已经完成该功能,前端还会添加进度条优化.对于导入导出功能,推荐这个Git:htt ...

  9. 《Docekr入门学习篇》——Docker仓库harbor

    Harbor Harbor仓库介绍 我们在日常Docker容器使用和管理过程中,渐渐发现部署企业私有仓库往往是很有必要的, 它可以帮助你管理企业的一些敏感镜像, 同时由于Docker Hub的下载速度 ...

  10. JunOS SRX firewal Web authentication(转)

    转载自:https://srxasa.wordpress.com/2011/12/11/junos-srx-firewal-web-authentication/ JunOS SRX firewal ...