回溯。
一个图只有两种情况,涂黑色或者涂白色,涂黑色或者涂白色其实都算访问过,这跟素数环那类题目不同,如果用循环的话一直往后走,并不是每次dfs都从头开始。我刚开始判断连通性的时候使全部涂完再判断,然后超时了。
又想了想,其实按照序号涂色,只需要判断这个标号之前的与新涂色的是否冲突就可以了,如果冲突,那就不用再往后回溯了,直接退一层。并不需要都涂完再检查。AC了。
做这题的时候还出现了Presentation error,一般是输出格式错误。
下面是TLE和AC的代码。
/**
TLE
*/
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N = 100 + 10;
int map[MAX_N][MAX_N];
int example[MAX_N];
int m,n,k,a,b,_max;
int vis[MAX_N];
bool solve()
{
for(int i = 1;i <= n;i++)
{
if(vis[i])
{
for(int j = 1;j <= n;j++)
{
if(map[i][j] && vis[j])
return false;
}
}
}
return true;
}
bool _solve(int i)
{
i = i - 1;
if(vis[i])
{
for(int j = 1;j < i;j++)
{
if(map[i][j] && vis[j])
return false;
}
}
return true;
}
void dfs(int cnt,int i)
{
if(_solve(i))
{
if(i == n + 1)
{
if(_max < cnt)
{
memcpy(example,vis,sizeof(int) * (n + 1));
_max = cnt;
}
}
else
{
vis[i] = 1;
dfs(cnt + 1,i + 1);
vis[i] = 0;
dfs(cnt,i + 1);
}
}
}
int main()
{
cin >> m;
while(m--)
{
_max = 0;
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
cin >> n >> k;
for(int i = 0;i < k;i++)
{
cin >> a >> b;
map[b][a] = map[a][b] = 1;
}
dfs(0,1);
cout << _max << endl;
int _cnt = 1;
for(int i = 1;i <= n;i++)
{
if(example[i] && _cnt < _max)
{
cout << i << " ";
_cnt++;
}
else if(example[i] && _cnt == _max)
cout << i << endl;
}
}
return 0;
}
/**
AC
*/
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N = 100 + 10;
int map[MAX_N][MAX_N];
int example[MAX_N];
int m,n,k,a,b,_max;
int vis[MAX_N];
void dfs(int cnt,int i)
{
if(i == n + 1)
{
if(solve())
{
if(_max < cnt)
{
memcpy(example,vis,sizeof(int) * (n + 1));
_max = cnt;
}
}
}
else
{
vis[i] = 1;
dfs(cnt + 1,i + 1);
vis[i] = 0;
dfs(cnt,i + 1);
}
}
int main()
{
cin >> m;
while(m--)
{
_max = 0;
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
cin >> n >> k;
for(int i = 0;i < k;i++)
{
cin >> a >> b;
map[b][a] = map[a][b] = 1;
}
dfs(0,1);
cout << _max << endl;
int _cnt = 1;
for(int i = 1;i <= n;i++)
{
if(example[i] && _cnt < _max)
{
cout << i << " ";
_cnt++;
}
else if(example[i] && _cnt == _max)
cout << i << endl;
}
cout << endl;
}
return 0;
}