二分图:
二分图是什么:顶点集可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。(边不能连接同一个子集的点)
图示:
二分图染色:
情况:给一个图,没有自环,没有同一条边连着多个点有两种颜色给你染,相连的两个点不能染成不同颜色
用途:可以用来判断是不是二分图
对于连通图思路:bfs遍历,第一个点取一种颜色,遍历的时候看看会不会产生冲突
代码(连通图):
int color[maxn];
vector<int>mp1[maxn];//双向
struct node
{
int u;
int v;
}mp[maxn];
bool bfs(int u)
{
memset(color,-1,sizeof(color));
queue<int>que;
que.push(u);
color[u]=1;
while(que.size())
{
int x=que.front();
que.pop();
for(int i=0;i<mp1[x].size();i++)
{
int y=mp1[x][i];
if(color[y]==-1)//如果未能染色
{
color[y]=color[x]^1;//与上一个相连结点颜色要不同
que.push(y);
}
else if(color[y]==color[x])//如果有冲突
{
return false;
}
}
}
return true;
}
对于不一定连通的图的思路: 把不同的连通块都跑一边bfs就好了,看是不是同一个连通块的只需要看上一次连通块bfs的结果里面color有没有染色。
代码(不一定连通):
int color[maxn];
int n,m;
bool bfs_tu(int u)
{
queue<int>que;
que.push(u);
color[u]=1;
while(que.size())
{
int x=que.front();
que.pop();
for(int i=1; i<=n; i++)
{
if(mp[x][i])
{
if(color[i]==-1)//如果未能染色
{
color[i]=color[x]^1;//与上一个相连结点颜色要不同
que.push(i);
}
else if(color[i]==color[x])//如果有冲突
{
return false;
}
}
}
}
return true;
}
bool match()
{
memset(color,-1,sizeof(color));
for(int i=1;i<=n;i++)
{
if(color[i]==-1)//如果没有染色,就说明这不在上一个连通块里
{
if(!bfs_tu(i))
return false;
}
}
return true;
}
F. Graph Without Long Directed Paths
题目链接:http://codeforces.com/contest/1144/problem/F
题目大意:给你一个连通图没有自环没有重复边,把无向图变成有向的,要求路径小于2(就是路径只能1)
思路:稍微理解一下,路径只能为一,那么一个点只能出点,那么与它连接的点就只能入点。这就变成了一道二分图染色题,相连的点必须一个出一个入。
代码:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <cstdlib>
#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int maxn=1e5*2+5;
int color[maxn];
vector<int>mp1[maxn];//双向
struct node
{
int u;
int v;
}mp[maxn];
bool bfs(int u)
{
memset(color,-1,sizeof(color));
queue<int>que;
que.push(u);
color[u]=1;
while(que.size())
{
int x=que.front();
que.pop();
for(int i=0;i<mp1[x].size();i++)
{
int y=mp1[x][i];
if(color[y]==-1)
{
color[y]=color[x]^1;
que.push(y);
}
else if(color[y]==color[x])//如果有冲突
{
return false;
}
}
}
return true;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[i].u=x;
mp[i].v=y;
mp1[x].push_back(y);
mp1[y].push_back(x);//双向,没双向wa了
}
int flag=bfs(1);
if(flag)
{
printf("YES\n");
for(int i=0;i<m;i++)
{
if(color[mp[i].u])
printf("1");
else
printf("0");
}
}
else
{
printf("NO\n");
}
return 0;
}