日常闲话:啊,这道题真的是给新手做的吗?可能是我太菜了(我连费费的答案也没看懂)(网上搜的子团也没看懂),最后好不容易理解了DFS剪枝这个做法,那就介绍介绍这个用法吧。
题目:
输入:
1
6 8
1 2
1 3
2 4
2 5
3 4
3 6
4 6
5 6
输出:
3
1 4 5
题目分析:
1.大体结构还是建图->dfs->输出记录的个数->输出记录的点。
2.重点还是在于这个dfs我们该怎么写?
a.首先要定义一个临时变量temp数组用来存储已经染黑的点,当扫描完所有的点时,更新更优的黑色点数值,并将临时变量装入black这个数组这个记录黑色点位置的数组中去。
3.剪枝思想:如果现在所有标记过的黑点+所剩余的点仍然小于已经搜到的最大黑点数(ans)时,我就直接return程序。
4.还有一个非常重要的点就是,如何判断这个点能不能染成黑色。(判断这两个点之间是否有路,或者这搜到的是同一个点时,就执行下一个循环)
大体的思路就是在这样,代码如下:
#include <iostream>
using namespace std;
const int maxn = 120;
//vector<int>mp[maxn];
int mp[maxn][maxn];
int temp[maxn];//建立临时变量数组
int black[maxn];
int n, m, x, y;
int ans = 0;
void dfs(int index, int x) {//index代表有几个点染成了黑色,x代表到达了第几个点。
if (x > n) {
if (ans < index) {
ans = index;//更新
for (int i = 0; i < ans; i++) {
black[i] = temp[i];//更新数组的值赋值到专门储存黑色的位置的数组里
}
}
return;
}
if (index + n - x < ans) {
return;//剪枝操作
}
dfs(index, x + 1);
bool flag = 1;//测试值
for (int i = 0; i < index; i++) {//判断该点是否能够染色。
int v = temp[i];
if (mp[v][x]||v==x) {//是否这个染色的点会和x有冲突:相邻或者根本就是一个点
flag = 0;//不能染色
break;
}
}
if (flag) {
temp[index] = x;//染色的这个点在图中的位置
dfs(index + 1, x + 1);
}
return;
}
int main()
{
int t;
cin >> t;
while (t--) {
cin >> n >> m;
ans = 0;
memset(mp, 0, sizeof mp);
while (m--) {
cin >> x >> y;
mp[x][y]= 1;
mp[y][x] = 1;
}
dfs(0, 1);//关键来了dfs如何去写
cout << ans << endl;
for (int i = 0; i < ans; i++) {
cout << black[i] << " ";
}
cout << endl;
}
}
借鉴的是->
感谢大佬的帮助,让本菜菜理解并做出了这个题,更加加深了对剪枝的理解。今晚任务还未结束,持续更新...算法问题欢迎及时交流!!!