连通图的DFS,BFS,并查集的试探

自己的DFS,样例没过,果然还是菜

#include <iostream>
#include<cstdio>
#define n 100
using namespace std;
int v,s;
//int flag[n];

int DFS(int G[][n],int s )
{
	int count = 0;

	int vis[n] = { 0 };
	vis[s] = 1;
	/*遍历所有节点*/
	for (int i = 0; i < v; i++)
	{
		if (vis[s] == 0 && G[s][i] == 1)
			count++;
	}
	if (count == v)
		return 1;
	else
		return 0;


}
int main()
{
	int sum = 0;
	scanf("%d%d", &v, &s);
	int G[n][n] = { 0 };
	for (int i = 0; i < s; i++)
	{
		int ti, tj;
		scanf("%d%d", &ti, &tj);
		G[ti][tj] = 1;
	}
//DFS
	for (int i = 0; i < v; i++)
	{
		int t;
		t=DFS(G, i);
		sum += t;
		
	}
	if (sum == v)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
}

我的想法是从某一点出发开始深搜,只需要判断最后count的值是否为节点数,小于是不连通的,相等是连通的。

某DFS正确写法

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int way[1010][1010];
int visited[1010];
void DFS(int x, int n)
{
	int i;
	visited[x] = 1;
	for (i = 1; i <= n; i++)
	{
		if (way[x][i] == 1 && visited[i] == 0)
		{
			DFS(i, n);
		}
	}
}
int main()
{
	int i, n, m, x, y;
	scanf("%d %d", &n, &m);

		memset(way, 0, sizeof(way));
		memset(visited, 0, sizeof(visited));
		for (i = 0; i < m; i++)
		{
			scanf("%d %d", &x, &y);
			way[x][y] = 1;
			way[y][x] = 1;
		}
		DFS(1, n);
		int flag = 0;
		for (i = 1; i <= n; i++)
		{
			if (visited[i] == 0)
				flag = 1;
		}
		if (flag == 1)
			printf("NO\n");
		else
			printf("YES\n");

	return 0;
}

来一块块分析:
首先DFS部分:非常正规,但是把for循环的条件改成从0-n-1答案错误

void DFS(int x, int n)
{
	int i;
	visited[x] = 1;
	for (i = 1; i <=n; i++)
	{
		if (way[x][i] == 1 && visited[i] == 0)
		{
			DFS(i, n);
		}
	}
}

主函数部分:

 int main()
{
	int i, n, m, x, y;
	scanf("%d %d", &n, &m);

		memset(way, 0, sizeof(way));
		memset(visited, 0, sizeof(visited));
		for (i = 0; i < m; i++)
		{
			scanf("%d %d", &x, &y);
			way[x][y] = 1;
			way[y][x] = 1;
		}
		//问题1:为什么从1开始?
		DFS(1, n);
		int flag = 0;
		//这里仍不能改成0-n-1;
		for (i = 1; i <= n; i++)
		{
			if (visited[i] == 0)
				flag = 1;
		}
		if (flag == 1)
			printf("NO\n");
		else
			printf("YES\n");

	return 0;
}

BFS的解决办法
我。。搬的,现在分析分析
知识点:
1Vector:
clear// 清除的使用

  1. vector::clear()函数的作用是清空容器中的内容,但如果是指针对象的话,并不能清空其内容,必须要像以下方法一样才能达到清空指针对象的内容,但并不回收内存

    vector xx;
    for(int it=0;it!=xx.size();++it)
    {
    xx.clear();
    }

  2. vector::erase()用于清空容器中的内容以及释放内存,并返回指向删除元素的下一个元素的迭代器。

  3. begin函数:
    功能:返回一个当前vector容器中起始元素的迭代器。
    end函数:
    功能:返回一个当前vector容器中末尾元素的迭代器。
    push_bach函数:
    ·功能:在容器的尾端插入一个数据
    4 memset
    memset函数初始化int数组时还可以初始化为-1和0.true和false等价于0
    2bool:是C++的关键字,一种数据类型,1.bool类型一般用一个字节存储,int根据平台不同,大小不同。一般在结构体中,bool只是二值的,用一个字节有点浪费空间,会使bool只占一位.类型转换,一个算术,枚举,指针,指向成员的右值,可以转换为bool。零,null pointer, null member pointer 可以转为false,其它的是true

  4. true可以提升为1,false可以提升为2

    #include
    #include
    #include //容器
    #include
    #include //算法
    #include //队列

    using namespace std;
    const int MAXN=1000002;
    vector g[MAXN];
    bool vis[MAXN];
    int n,m;
    void bfs(int s)
    {
    //用队列广搜
    queue q;
    q.push(s);
    while(!q.empty())
    {
    int x=q.front();
    q.pop();
    vis[x]=true;
    for(int i=0;i<g[x].size();++i)
    {
    if(vis[g[x][i]])
    g[x].erase(g[x].begin()+i);
    //删除图中已经遍历过的点,可提高遍历速度
    else
    q.push(g[x][i]);
    }
    }
    }

     bool judge()
     {
     //判断是否所有点已被遍历过
         for(int i=1;i<=n;++i)
                 if(!vis[i])
                     return false;
                     return true;
     }
     int main()
     {
            scanf("%d%d",&n,&m);
                for(int i=1;i<=n;++i) 
                {
                		g[i].clear();
                	}
                 for(int i=0;i<m;++i)
                 {
                    int a,b;
                    scanf("%d%d",&a,&b);
             	  g[a].push_back(b); 
             	    //无向图转化为有向图,正反两次存入连接表。
                       g[b].push_back(a);
                     }
     	       memset(vis,false,sizeof(vis));
                 bfs(1);
                 if(judge())
                     printf("YES\n");
                 else printf("NO\n");
                 }
             return 0;
     }
    

并查集

#include<stdio.h>
int map[1005];
int n,m;
int find(int i)
{
    return map[i]==i?i:find(map[i]);
}
void init()
{
    for(int i=0;i<n;i++)
    map[i]=i;
}
int main()
{
  scanf("%d%d",&n,&m);
    
        if(n==0) break;
        init();
        int a,b;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            a--;b--;
            map[find(a)]=map[find(b)];
        }
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            if(map[i]==i)
            cnt++;
        }
        if(cnt==1)
        printf("YES\n");
        else
        printf("NO\n");
    
    return 0;
}

https://blog.csdn.net/u013546077/article/details/64509038
明天在分析,要阵亡了,终于要迎来大一第一个寒假,哈哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值