1023 新集合 dfs
链接:https://ac.nowcoder.com/acm/contest/23156/1023
来源:牛客网
题目描述
现在牛妹给牛牛加了 mmm 个限制 ,每个限制包含两个整数 uuu 和 vvv ( u≠vu\neq vu=v),且 uuu 和 vvv 不能同时出现在新集合中 。
请问牛牛能组成的新集合多少种。
可以选 0 个数。
返回一个整数,即新集合的种类数。
备注:
第一个参数为 nnn。
第二个参数为 mmm 。
第三个参数为 mmm 对 (u, v) 。
1<n≤201≤m≤4001≤u,v≤n1 < n \leq 20 \quad 1\leq m \leq 400\quad 1 \leq u, v\leq n1<n≤201≤m≤4001≤u,v≤n
分析
1.就是有多少集合数量,那组合一遍就可以了
2.但是那时候对求排列其实有点不知道怎么下手。。。。我好菜。。其实就是每取一个数都是一个新的排列,然后从小到大逐个加入删除就行。
3.但是这里有一个不能在一起的数。那个时候想的是,把每个已经加到序列中的数的对应的数的vis 都弄成true。然后返回的时候把vis 变成false。但这样返回的时候可能会把对于前面也是这样的数删除
就是可能有条件重合的数。
4.看了题解才知道直接给每个数一个权值,表示这个数被多少个数讨厌,递归的时候再让这个讨厌值+1-1。
5.然后就到了经典的语法bug。vector<vector<int>> mp(30);老是报错
6.然后改成数组就过了。然后vector<int> mp[30] 也可以过。。。
/**
* struct Point {
* int x;
* int y;
* Point(int xx, int yy) : x(xx), y(yy) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int 集合大小
* @param m int 限制数量
* @param limit Pointvector 不能同时出现的(u,v)集合
* @return int
*/
//基本状态压缩吧
public:
int N = 30;
int vis[30];
vector<int> mp[30];//这样就可以了???
int nn = 0;
int sum = 0;
int ms[30][30];
void dfs(int start) {
sum ++ ;
for(int i = start;i<=nn;i++) {
if(!vis[i]) {
vis[i] ++ ;
for(int k = i + 1;k<=nn;k++) {if(find(mp[i].begin(),mp[i].end(),k) != mp[i].end()) {vis[k] ++ ;} }
// for(int k = i + 1;k<=nn;k++){ if(ms[i][k] == 1) {vis[k] ++ ;} }
dfs(i + 1);
// for(int k = i + 1;k<=nn;k++) {if(ms[i][k] == 1) {vis[k] -- ;} }
for(int k = i + 1;k<=nn;k++) {if(find(mp[i].begin(),mp[i].end(),k) != mp[i].end()) {vis[k] -- ;} }
vis[i] -- ;
}
}
}
int solve(int n, int m, vector<Point>& limit) {
// write code here
nn = n;
for(int i = 0;i<m;i++) {
int x = limit[i].x,y = limit[i].y;
// ms[x][y] = 1,ms[y][x] = 1;
mp[x].push_back(y),mp[y].push_back(x);
}
dfs(1);
return sum;
}
};