#include<cstdio> #include<string.h> #include<iostream> #include<algorithm> #include<vector> #include<string> #include<queue> #include<map> #include<stack> using namespace std; int d[105][105]; //d[i][j]=x 第i个教室 第j个学生编号x int cnt[105]; int mp[105][105]; int minn = 10000000; //思路:遍历所有情况,加入这个学生,或不加入这个学生,中途剪枝 int n,m; /* void dfs(int no,int tot) //目前有tot个教室,考虑将编号no的学生编入教室 { if(tot >= minn) return; //剪枝 if(no > n) { if(tot < minn) minn = tot; return; } int f1 = 0; for(int i=1;i<=tot;i++) { f1 = 0; for(int j=1;j<=n;j++) { if(d[i][j]==1) //第i间教室有个编号为j的学生 { if(mp[no][j] == 1) //j和no认识,no无法编入i教室 { f1 = 1; break; } } } if(f1 == 0) //第i间教室无人认识no { d[i][no]=1; dfs(no+1,tot); //编入no d[i][no]=0; //不编入no } } //仍无法编入no d[tot+1][no] = 1; dfs(no+1,tot+1); //已经得到无法编入no的情况下的教室数目 d[tot+1][no] = 0; //错误点,没有重置 } */ //超时原因: d[i][j]=1 第i个教室 有编号为j的学生 ,这种存储结构导致每次都需要遍历n次 //改进方法: d[i][j]=x 第i个教室 第j个人的编号为x void dfs(int no,int tot) //目前有tot个教室,考虑将编号no的学生编入教室 { if(tot >= minn) return; //剪枝 if(no > n) { if(tot < minn) minn = tot; return; } int ct = 0; for(int i=1;i<=tot;i++) { ct = 0; for(int j=1;j<=cnt[i];j++) //d[i][j]=x ,x为编号 { if(mp[no][d[i][j]] == 1) //x和no认识,no无法编入i教室 break; else ct++; } if(ct == cnt[i]) //第i间教室无人认识no { cnt[i]++; d[i][cnt[i]]=no; dfs(no+1,tot); //编入no cnt[i]--; //不编入no } } //仍无法编入no cnt[tot+1]++; d[tot+1][cnt[tot+1]] = no; dfs(no+1,tot+1); //已经得到无法编入no的情况下的教室数目 cnt[tot+1]--; //重置 } int main() { scanf("%d%d",&n,&m); memset(mp,0,sizeof(mp)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { cnt[i] = 0; for(int j=1;j<=n;j++) { mp[i][j] = 0; d[i][j] = 0; } } for(int i=1;i<=m;i++) { int a,b; scanf("%d %d",&a,&b); mp[a][b] = 1; mp[b][a] = 1; } dfs(1,1); printf("%d",minn); return 0; }
原文:https://www.cnblogs.com/fzuhyj/p/10558896.html