HDU1269 迷宫城堡
题目大意
给定 有向图 中的 n 个点, m 条边, 求图的 强连同分量 是否为 1.
题目思路
一道裸的 tarjan 题, 需要注意的是边的存储, LOW的含义.
代码
#include <cstdio>
#include <cstring>
#include <stack>
#include <cmath>
#define MAXN 10100
#define MAXM 100100
using namespace std;
struct Edge{
int v, next;
}edge[MAXM];
int vis[MAXN];
int head[MAXN];
int DFN[MAXN];
int LOW[MAXN];
int cntSCC, cntVertex, cntEdge;
stack<int> stk;
void init(){
memset(vis, 0, sizeof(vis));
memset(head, -1, sizeof(head));
memset(DFN, 0, sizeof(DFN));
memset(LOW, 0, sizeof(LOW));
cntEdge = cntSCC = 0;
cntVertex = 1;
while(!stk.empty())
stk.pop();
}
void addEdge(int u, int v){
edge[cntEdge].next = head[u];
edge[cntEdge].v = v;
head[u] = cntEdge;
cntEdge++;
}
void tarjan(int loc){
DFN[loc] = LOW[loc] = cntVertex++;
vis[loc] = 1;
stk.push(loc);
for(int i = head[loc]; i != -1; i = edge[i].next){
if(!DFN[edge[i].v]){
tarjan(edge[i].v);
LOW[loc] = min(LOW[loc], LOW[edge[i].v]);
}
else if(vis[edge[i].v]){
LOW[loc] = min(LOW[loc], DFN[edge[i].v]);
}
}
if(DFN[loc] == LOW[loc]){
cntSCC++;
int temp;
do{
temp = stk.top();
stk.pop();
vis[temp] = 0;
}while(temp != loc);
}
}
int main(){
int nVertex, nEdge;
while(scanf("%d%d", &nVertex, &nEdge) && nVertex){
init();
for(int i = 0; i < nEdge; i++){
int a, b;
scanf("%d %d", &a, &b);
addEdge(a, b);
}
for(int i = 1; i <= nVertex; i++)
if(!DFN[i]) tarjan(i);
printf("%s\n", cntSCC == 1 ? "Yes" : "No");
}
return 0;
}