题意:中文题,就是根据给出的一些有向边,判断所有的点是不是在一个强连通里。最最基本的tarjan了,用链式前向星的加边方式。
tarjan算法:tarjan
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 10010;
const int maxm = 100010;
struct edge{
int v;
int nex;
}e[maxm];
int head[maxn] , k;
void addedge(int a , int b) {
e[k].v = b;
e[k].nex = head[a];
head[a] = k++;
}
int dfn[maxn] , low[maxn] , sta[maxn] , vis[maxn] , atype , top , times , flag;
void tarjan(int u) {
sta[++top] = u;
vis[u] = 1;
dfn[u] = low[u] = times++;
for(int i = head[u] ; i != -1 ; i = e[i].nex) {
int v = e[i].v;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u] , low[v]);
} else if(vis[v]) {
low[u] = min(low[u] , dfn[v]);
}
}
int j;
if(dfn[u] == low[u]) {
++atype;
if(atype > 1) {
flag = 0;
return;
}
do {
j = sta[top--];
vis[j] = 0;
}while(j!=u);
}
}
int main() {
int N , M;
while(~scanf("%d%d",&N,&M)) {
if(!N && !M) break;
int a , b;
memset(head , -1 , sizeof(head));
k = 1;
while(M--) {
scanf("%d%d",&a,&b);
addedge(a , b);
}
memset(vis , 0 , sizeof(vis));
memset(dfn , 0 , sizeof(dfn));
memset(low , 0 , sizeof(low));
memset(sta , 0 , sizeof(sta));
atype = 0;
times = top = 1;
int i;
flag = 1;
for(i = 1 ; i <= N ; i ++) {
if(!dfn[i]) tarjan(i);
}
if(flag) printf("Yes\n");
else printf("No\n");
}
}