Divide Groups(二分图+dfs+连通块+邻接表)

13 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
题意:给你i认识j但是不具有对称性,也就是j不认识i;然后问是否能分为两组,两组中都是认识的人;
我头一次写二分图,最原始的二分图是是否相邻的能被两种不同的颜色染色;然后这道题可以这样抽象:
把不同的人当做顶点,如果两个人不认识就加边:
比如1不认识2,2不认识3,那么:
在这里插入图片描述
很明显这个图是二分图;因为1号顶点可被染成1的颜色,2号顶点可以被染成-1的颜色,3号顶点可以被染成1颜色;所以这道题就是去找不认识的人然后用邻接表建立一个无向图;之后dfs遍历所有连通块,因为如果1,2,3都互相认识那么建立的图就应该是:
在这里插入图片描述
这样就可以随便染色了;所以需要用一个for+dfs遍历所有连通块:
AC代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=200;
int color[maxn];
int R[200][200];
vector<int> edge[maxn];
bool dfs(int v,int c){
	  color[v]=c;
	  for(int i=0;i<edge[v].size();i++){//遍历v点所能到达的点
	  	   if(color[edge[v][i]]==c)return false;//如果被染为一样的就false
	  	   if(color[edge[v][i]]==0&&!dfs(edge[v][i],-c))return false;//如果没有颜色,那么看一下一点是否满足条件
	  }
	  return true;//如果都OK,就返回true
}
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		memset(color,0,sizeof(color));//注意每次更新
		memset(R,0,sizeof(R));
		for(int i=0;i<maxn;i++)edge[i].clear();
		int a;
		for(int i=1;i<=n;i++){
			 while(scanf("%d",&a)&&a){
			 	R[i][a]=1;
			 }
		}
		for(int i=1;i<=n;i++){
			  for(int j=1;j<=n;j++){
			  	if(i==j)continue;
			  	  if(R[i][j]==0){//建立无向图,因为i不认识j所以根据图应该是建立双向的
			  	  	    edge[i].push_back(j);
			  	  	    edge[j].push_back(i);
					}
			  }
		}
		int f=0;
		for(int i=1;i<=n;i++){//遍历所有连通块
			if(color[i]==0){
		     	if(!dfs(i,1)){
				puts("NO");f=1;break;
			}
		   }
		}
	   if(!f)puts("YES");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值