请设计一个算法判断无向图G是否为一棵树,若是树,则返回1;否则,返回0。
解题思路:jt要注意无向图和有向图建图时的区别;用深搜遍历图,记录边数和顶点数,若边数=2*(顶点数-1),则是无向图树。因为在无向图里,每条边存了两次。
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int MAXN=100;
typedef struct ArcNode//边表结点
{
int adjvex;
ArcNode *nextvex;
};
typedef struct Vnode//顶点表结点
{
int data;
ArcNode *firstvex;
};
typedef struct Graph//图
{
Vnode adjlist[MAXN];
int n;
int e;
}*graph;
graph g=(graph)malloc(sizeof(Graph));
void build(graph g)//用邻接表存储图
{
printf("n,e==");
scanf("%d%d",&g->n,&g->e);
for(int k=1;k<=g->n;k++)
{
g->adjlist[k].data=k;
g->adjlist[k].firstvex=NULL;
}
printf("输入边边的from和to:\n");
int i,j;
for(int k=1;k<=g->e;k++)
{
scanf("%d%d",&i,&j);
ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->nextvex=g->adjlist[i].firstvex;
g->adjlist[i].firstvex=p;
//如果是有向图,则没有下面的代码
ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
q->adjvex=i;
q->nextvex=g->adjlist[j].firstvex;
g->adjlist[j].firstvex=q;
}
}
void print(graph g)//输出邻接表存储的图
{
for(int k=1;k<=g->n;k++)
{
printf("%d ",g->adjlist[k].data);
ArcNode *p=g->adjlist[k].firstvex;
while(p!=NULL)
{
printf("%d ",p->adjvex);
p=p->nextvex;
}
printf("\n");
}
}
int visit[100];//标记数组
int nnum=0;//记录顶点数
int ednum=0;//记录边条数
void dfs(graph g,int v,int &nnum,int &ednum)//深搜
{
visit[v]=1;
nnum++;
ArcNode *p=g->adjlist[v].firstvex;
while(p!=NULL)
{
ednum++;//p不为空说明存在一条边
if(visit[p->adjvex]==0)
{
dfs(g,p->adjvex,nnum,ednum);
}
p=p->nextvex;
}
}
bool isTree(graph g)
{
memset(visit,0,sizeof(visit));
dfs(g,1,nnum,ednum);
if(nnum==g->n&&ednum==2*(g->n -1)) return true;//无向图树的特点
}
int main()
{
build(g);
print(g);
if(isTree(g))
{
printf("是\n");
}
else printf("否\n");
return 0;
}
/*非树测试数据
5 5
1 2
1 3
2 4
3 4
4 5
*/
/*树测试数据
5 4
1 2
1 3
2 4
3 5
*/