题目描述:原题描述很清楚了,地址是:http://acm.hdu.edu.cn/showproblem.php?pid=1269
分析:很简单的模板题,只要看一下是不是强连通图就可以。用一遍tarjan,看在一个集合里的点数是否等于所有点点数N。
由于是练习赛,直接拿前面写过的题目poj2186的代码改了改,代码如下:
#include<stdio.h>
#include<string.h>
#define max_n 10005
#define max_e 100005
int stack[max_n], top; //栈
bool visited[max_n]; //该点是否在栈中
int low[max_n]; //点的low值
int dfn[max_n], times; //点的dfn值 time从1开始
//////////////////
int Node_num;//缩点后node含点的个数 type从1开始
///////////////////
int head[max_n], s_edge;//邻接表头 s_edge从1开始
struct E{
int to, next;
}edge[max_e]; //邻接表
void init(){
top = 0;
memset(visited, 0, sizeof(visited));
memset(low, 0, sizeof(low));
memset(dfn, 0, sizeof(dfn)); times = 0;
Node_num = 0;
memset(head, 0, sizeof(head)); s_edge = 0;
memset(edge, 0, sizeof(edge));
}
void add_in_edge(int u, int v){
s_edge++;
edge[s_edge].to = v;
edge[s_edge].next = head[u];
head[u] = s_edge;
}
int min(int a, int b){
if(a<b) return a;
else return b;
}
//tarjan是用dfs实现的一深搜棵树
void tarjan(int u){ //low值为u或u的子树能够追溯到得最早的栈中节点的次序号
stack[top++] = u;
visited[u] = true;
dfn[u] = ++times; //记录点u出现的记录,并放在栈中
low[u] = times;
int e, v;
for(e=head[u]; e; e = edge[e].next){//如果是叶子节点,head[u]=0,edge[e].next=0;
v = edge[e].to;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(visited[v])
low[u] = min(low[u], dfn[v]);
}
int j;
if(dfn[u] == low[u]){
Node_num = 0;
while(j = stack[--top]){//退栈
visited[j] = false;
Node_num++;
if(j == u)
break;
}
}
}
int main(){
int N, M, A, B;
int i;
while(scanf("%d %d",&N, &M) && N){
init();
for(i=0; i<M; i++){
scanf("%d %d",&A, &B);
add_in_edge(A, B);
}
tarjan(1);
if(Node_num == N)
printf("Yes\n");
else printf("No\n");
}
return 0;
}