经典的图的染色问题,求对于给定的无向图中,给每个结点染两种不同颜色(黑色和白色)的一种且相邻结点的颜色不同,求染成黑色的最多结点数。
解法是二分最多结点数+dfs,很简单,不详细解释了。
以下是代码:
- #include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int M=110;
bool map[M][M],vis[M];
int color[M],stack1[M],stack2[M];
int top1,top2;
int cnt;
int n,m; - void init()
{
memset(map,0,sizeof(map));
} - bool check(int s)
{
int i;
for(i=1;i<=n;i++)
if(map[s][i] && vis[i] && color[i]==1) return false;
return true;
} - void dfs(int s,int mid)
{
int i;
for(i=1;i<=n;i++)
{
if(map[s][i] && !vis[i])
{
vis[i]=1;
if(check(i))
{
color[i]=1;
cnt++;
stack2[top2++]=i;
if(cnt==mid) return ;
dfs(i,mid);
}
else
{
color[i]=0;
dfs(i,mid);
}
}
}
} - int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int i,j;
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d",&i,&j);
map[i][j]=map[j][i]=1;
}
int low=0,high=n;
int ans=n/2;
while(low<=high)
{
int mid=(low+high)>>1;
bool flag=false;
for(i=1;i<=n;i++)
{
memset(color,0,sizeof(color));
memset(vis,0,sizeof(vis));
color[i]=1;
vis[i]=1;
cnt=top2=1;
stack2[0]=i;
dfs(i,mid);
if(mid==cnt)
{
ans=mid;
memcpy(stack1,stack2,sizeof(stack1));
top1=top2;
flag=true;
break;
}
}
if(flag)
{
low=mid+1;
}
else high=mid-1;
}
printf("%d/n",ans);
for(i=0;i<top1;i++)
printf("%d ",stack1[i]);
printf("/n");
}
return 0;
}