题目:
分析:
看到题目 b b bb bb一堆,这里我们转换下:
在有n个节点的图中,每个节点的度数不超过3,现在要我们对其进行黑白染色,使得相邻节点中只出现至多2个相同颜色的节点
现在我们很容易想到用二分图做,但本蒟蒻不会呀,可仍然有更优更简单的方法:用
d
f
s
dfs
dfs来进行黑白染色
怎么讲呢,我们通过
d
f
s
dfs
dfs不断更正我们的答案
首先对于当前节点
(
n
o
w
)
(now)
(now)的字节点
(
u
)
(u)
(u),当
u
u
u没有答案时,我们将以
n
o
w
now
now的答案取反填入,再以
u
u
u进行
d
f
s
dfs
dfs
可显然,会在这个过程中出现多个相同颜色的节点,那么我们可以考虑在
d
f
s
dfs
dfs求出子节点的答案后统计与
n
o
w
now
now相同颜色的节点数,遍历完所有子节点后,当统计的数
>
1
>1
>1(即有多个相同颜色的节点),我们就可以直接将
n
o
w
now
now的答案取反
至此,本题就基本结束了
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
#define ch cheap
#define XJQ (int)1000000007
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
int t,n;
}t[300005];
int ls[300005],cnt=0;
int ans[(int)1e5+5];
void dfs(int now)
{
int sum=0;
for(int i=ls[now];~i;i=t[i].n)
{
int u=t[i].t;
if(!ans[u]) ans[u]=ans[now]^3,dfs(u);
if(ans[now]==ans[u]) sum++;
}
if(sum>1) ans[now]^=3;
return;
}
int main()
{
int n=read(),m=read();
memset(ls,-1,sizeof(ls));
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
t[cnt]=(node){y,ls[x]};ls[x]=cnt++;
t[cnt]=(node){x,ls[y]};ls[y]=cnt++;
}
for(int i=1;i<=n;i++)
{
if(!ans[i]) ans[i]=1,dfs(i);
printf("%d ",ans[i]);
}
return 0;
}
玄中之玄:
用该种算法,是不能做到 A C AC AC题目样例的,但因为有 S p e c i a l Special Special J u d i n g Juding Juding,所以还是可以 A A A的