图只有树边和反向边,如果有反向边那么就有环,否则就是树或森林。
有向图的code如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=1001;
int vis[maxn];
int map[maxn][maxn];
int flag;
int n,m;
void input()
{
memset(vis,0,sizeof(vis));
memset(map,0,sizeof(map));
scanf("%d %d",&n,&m);
for(int i=0;i<m;++i)
{
int a,b;
scanf("%d %d",&a,&b);
map[a][b]=1;
}
}
int dfs(int v)
{
vis[v]=-1;
flag=0;
for(int i=1;i<=n;++i)
{
if(map[v][i]&&!vis[i])
{
dfs(i);
vis[i]=1;
}
if(map[v][i]&&vis[i]==-1)
{
flag=1;
break;
}
}
return flag;
}
void judge()
{
if(!flag)
printf("Not a circle\n");
else
printf("Yes\n");
return ;
}
int main()
{
input();
dfs(1);
judge();
return 0;
}
在进行深搜的时候,把深搜的点添加一个特殊标记,如果从当前的点往下搜的时候,发现这个标记,则立马判定有环
再一个加大神的code:
#include <stdio.h>
#include <list>
#include <stack>
using namespace std;
list<int> edge[10003];
int n, m, current, used[10003];
bool find;
void clear(int used[]) {
for (int i = 1; i <= n; ++i)
used[i] = 0;
}
void print(int used[]) {
for (int i = 1; i <= n; ++i)
printf("%d", used[i]);
printf("\n");
}
void dfs(int x) {
used[x] = 1;
for(list<int>::iterator it = edge[x].begin(); it != edge[x].end(); ++it) {
if(*it == current) find = 1;
if(find) break;
if(!used[*it])
dfs(*it);
}
if(!find) used[x] = 2;
}
void beginDFS(int x) {
find = 0;
clear(used);
dfs(current = x);
printf("%d: ", x);
print(used);
}
int main() {
if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
scanf("%d %d", &n, &m);
int x, y;
for (int i = 0; i < m; ++i) {
scanf("%d %d", &x, &y);
edge[x].push_back(y);
}
beginDFS(1); beginDFS(2); beginDFS(3); beginDFS(4); beginDFS(5);
return 0;
}
这是一个有向图是否有环,是判断某个点在不在环内 并输出环上的点
0是无法达到的点
1是能达到而且在环中的点
2是能达到但是不在环中的点
无向图的code:
#include <iostream>
using namespace std;
const int M=501;
bool g[M][M];
bool visit[M];
bool flag;
int v,e;
bool dfs(int i,int pre)
{
visit[i]=true;
for(int j=1;j<=v;j++)
if(g[i][j])
{
if(!visit[j])
return dfs(j,i);
else if(j!=pre) //如果访问过,且不是其父节点,那么就构成环
return false;
}
}
int main()
{
int i,j;
while(cin>>v>>e)
{
memset(g,0,sizeof(g));
while(e--)
{
cin>>i>>j;
g[i][j]=g[j][i]=true;
}
memset(visit,0,sizeof(visit));
flag=dfs(1,0);
if(flag)
cout<<"no\n";
else
cout<<"yes\n";
}
return 0;
}
用并查集也阔以来判断是否有环,转载的一个大神的代码:
#include <iostream>
using namespace std;
int parent[100002];
int UFfind(int i)
{
int j;
for(j=i;parent[j]>0;j=parent[j]);
while(j!=i)
{
parent[i]=j;
i=parent[i];
}
return j;
}
void UFunion(int i,int j)
{
int temp=parent[i]+parent[j];
if(parent[i]<parent[j])
{
parent[j]=i;
parent[i]=temp;
}
else
{
parent[i]=j;
parent[j]=temp;
}
}
int main()
{
int p,q,c,i,j,a,b;
while(scanf("%d%d",&p,&q)!=EOF,!(p==-1&&q==-1))
{
c=0;
a=0;
b=p;
memset(parent,-1,sizeof(parent));
while(!(p==0&&q==0))
{
if(parent[p]==-1 && parent[q]==-1) //如果是两个独立点合并,则根节点数加1
a++;
else
if(parent[p]!=-1 && parent[q]!=-1) //如果p,q不是同一颗树,合并后根节点数减1,
//如果是同一颗树,那么在后面的判断中会把c改为1,不影响后面的结果
a--; //这样做很巧妙
i=UFfind(p);
j=UFfind(q);
if(i!=j)
UFunion(i,j);
else
c=1;
scanf("%d%d",&p,&q);
}
if(!c && a==1 || b==0)
printf("Yes\n");
else
printf("No\n");
}
}
如果图的父节点不止一个则一定不连通