问题描述:
给定一个无向图 G=(V,E),设 U⊆V 是 G 的顶点集。对任意(u,v)∈E,若有 u∈U 且 v∈V-U,就称(u,v)为关于顶点集 U 的一条割边。顶点集 U 的所有割边构成图 G 的一个割。
G 的最大割是指 G 中所含边数最多的割。
使用回溯法,无剪枝函数设计,到达叶节点后,比较目前解和当前已知最优解,若更优,更新最优解和结点是否加入U顶点集。目前解通过一个for二重循环,如果两个结点有边相连,且属于不同的顶点集,即cut[i] != cut[j],割边数加1。
cut[i] = 0表示i结点不在U中,1表示在U中。
AC代码
#include<iostream>
#include<cstring>
using namespace std;
#define MAX_NODE 999 //最大顶点数+1
int max_cut=0;
int n,m;
int cut_pos[MAX_NODE];
void cal_max_cut(int n,int m,bool is_connected[][MAX_NODE],int cut[],int i)
{
if(i==n+1)
{
int count=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(is_connected[i][j] && cut[i]!=cut[j])
count++;
}
}
if(count>max_cut)
{
max_cut=count;
for(int i=1;i<=n;i++)
{
if(cut[i] == 2)
{
cut_pos[i]=0;
continue;
}
cut_pos[i]=cut[i];
}
}
return;
}
cut[i]=1;
cal_max_cut(n,m,is_connected,cut,i+1);
cut[i]=2;
cal_max_cut(n,m,is_connected,cut,i+1);
}
int main()
{
cin>>n>>m;
bool is_connected[MAX_NODE][MAX_NODE];
memset(is_connected,false,sizeof(is_connected));
for(int i=0;i<m;i++)
{
int x,y;
cin>>x>>y;
is_connected[x][y]=true;
is_connected[y][x]=true;
}
int cut[n+1];
memset(cut,0,sizeof(cut));
cal_max_cut(n,m,is_connected,cut,1);
cout<<max_cut<<endl;
for(int i=1;i<=n;i++)
cout<<cut_pos[i]<<" ";
return 0;
}