题意:有N个山洞m条路,问任意两点x y 能否存在从x到y 或者从y到x。
思路:注意是或 而不是和。所以缩点后,不是判断强连通为1。
第一种方法:只要用拓扑判断入度为0的点是否为1个,如果有多个,就出现在分叉,不可能从x到y。
第二种方法:从入度为0的点 DFS 搜索 最长能到达的路径 如果路径长度等于点数,说明可以从源点访问完所有点。
第二种做法的代码:
#include <stdio.h>
#include <string.h>
#define VM 1005
#define EM 6005
struct E
{
int to,next;
}edge[EM],edge1[EM];
int head[VM],head1[VM],indeg[VM],outdeg[VM];
int dfn[VM],low[VM],vis[VM],belong[VM],stack[VM];
int scc,cnt,top,p,n;
void addedge (int cu,int cv,E ed[],int head0[])
{
ed[p].to = cv;
ed[p].next = head0[cu];
head0[cu] = p++;
}
void tarjan (int u)
{
int v;
dfn[u] = low[u] = ++cnt;
stack[top++] = u;
vis[u] = 1;
for (int i = head[u];i != -1;i = edge[i].next)
{
v = edge[i].to;
if (!dfn[v])
{
tarjan(v);
low[u] = low[u] > low[v]?low[v]:low[u];
}
else if (vis[v]&&low[u] > dfn[v])
low[u] = dfn[v];
}
if (dfn[u] == low[u])
{
++scc;
do
{
v = stack[--top];
vis[v] = 0;
belong[v] = scc;
} while (u != v);
}
}
void sovle ()
{
int u;
scc = top = cnt = 0;
memset (dfn,0,sizeof(dfn));
memset (vis,0,sizeof(vis));
for (u = 1;u <= n;u ++)
if (!dfn[u])
tarjan(u);
}
int dep[VM], maxdep;
int DFS(int u, int d) //找最长路径
{
int i, v;
dep[u] = d;
maxdep = maxdep > d ? maxdep : d;
for (i = head1[u]; i != -1; i = edge1[i].next)
{
v = edge1[i].to;
if (dep[u] > dep[v])
DFS(v, d + 1);
}
return 0;
}
int ans()
{
int u,v,i;
memset (indeg,0,sizeof(indeg));
// memset (outdeg,0,sizeof(outdeg));
//memset (count,0,sizeof(count));
for (u = 1;u <= n;u ++)
for (i = head[u];i != -1;i = edge[i].next)
{
v = edge[i].to;
if (belong[u] != belong[v])
{
indeg[belong[v]] ++;
//
outdeg[belong[u]] ++;
addedge (belong[u],belong[v],edge1,head1);
//建新图
}
}
maxdep = 0;
for (u = 1;u <= n;u ++)
if (!indeg[u])
{
DFS(u,1);
break;
}
if (maxdep == scc)
return 1;
return 0;
}
int main ()
{
int t,m,u,v;
scanf ("%d",&t);
while (t --)
{
p = 0;
memset (head1,-1,sizeof(head1));
memset (head,-1,sizeof(head));
scanf ("%d%d",&n,&m);
while (m --)
{
scanf ("%d%d",&u,&v);
addedge (u,v,edge,head);
}
sovle ();
if (ans())
printf ("Yes\n");
else
printf("No\n");
}
return 0;
}
思路:注意是或 而不是和。所以缩点后,不是判断强连通为1。
第一种方法:只要用拓扑判断入度为0的点是否为1个,如果有多个,就出现在分叉,不可能从x到y。
第二种方法:从入度为0的点 DFS 搜索 最长能到达的路径 如果路径长度等于点数,说明可以从源点访问完所有点。
第二种做法的代码:
#include <stdio.h>
#include <string.h>
#define VM 1005
#define EM 6005
struct E
{
}edge[EM],edge1[EM];
int head[VM],head1[VM],indeg[VM],outdeg[VM];
int dfn[VM],low[VM],vis[VM],belong[VM],stack[VM];
int scc,cnt,top,p,n;
void addedge (int cu,int cv,E ed[],int head0[])
{
}
void tarjan (int u)
{
}
void sovle ()
{
}
int dep[VM], maxdep;
int DFS(int u, int d) //找最长路径
{
}
int ans()
{
}
int main ()
{
}