因为一次考试中一道题涉及到2-SAT,2-SAT又涉及到强连通分量TAT,于是怒学;
对于此算法的讲解:
参见byvoid博客;
(以下样例中用图也来自此blog)
自己测试用样例(输出每个节点所在的scc):
trajan.in
6 8
1 3
1 2
2 4
3 4
3 5
4 1
4 6
5 6
trajan.out
3 3 3 3 2 1
自己打的一个小模板:
#include
#include
#include
#include
#include
using namespace std;
#define maxn 100 + 10
#define maxm 10000 + 10
#define INF 0x7f7f7f7f
int front[maxn], dfn[maxn], low[maxn], belong[maxn], que[maxn]; bool vis[maxn];
int n, m, cur, scc, index, top;
struct edge{
int to, next;
}e[maxm];
inline void addedge(int u, int v){
e[++ cur].to = v; e[cur].next = front[u]; front[u] = cur;
}
inline void trajan(int u){
dfn[u] = low[u] = ++ index;
que[++ top] = u; vis[u] = 1;
for(int i = front[u]; i; i = e[i].next)
if(!dfn[e[i].to])
trajan(e[i].to), low[u] = min(low[u], low[e[i].to]);
else if(vis[e[i].to])
low[u] = min(low[u], dfn[e[i].to]);
int now = -1;
if(low[u] == dfn[u]){
scc++;
while(now != u){
now = que[top --];
belong[now] = scc;
vis[now] = 0;
}
}
}
int main(){
freopen("trajan.in","r",stdin); freopen("trajan.out","w", stdout);
cur = scc = top = index = 0;
memset(dfn, 0, sizeof(dfn));
scanf("%d%d", &n, &m);
while(m --){
int u, v; scanf("%d%d",&u, &v);
addedge(u,v);
}
for(int i = 1; i <= n; i ++)
if(!dfn[i]) trajan(i);
for(int i = 1; i <= n; i ++)
printf("%d%c", belong[i], (i == n) ? '\n' : ' ');
fclose(stdin); fclose(stdout);
return 0;
}