HDU
来源:互联网 发布:好听的改编网络歌曲 编辑:程序博客网 时间:2024/06/15 15:07
传送门
//题意: 给定一幅n个点, m条边的图, 问有多少个恰好有S个顶点的完全子图?
//思路: 这道题的想法炒鸡棒, 要学到. 因为s最大10. 点数最多也才100. 完全可以用暴力搜索. 问题有一点, 如何避免搜重? 所以这里就非常有意思了. 我们建图时建有向的有序边. 即我们只从编号小的到编号大的(或者反着, 必须有序)建有向边. 而连接性我们双向标记. 这样我们在暴力每个点搜索时不仅可以搜出答案 , 并且不会搜重. 只要想到这里, 就应该好写了. 剩下的就是普通的深搜出每一种答案.
AC Code
/** @Cain*/const int maxn = 1e2+5;int cnt,head[maxn];bool mapp[maxn][maxn],vis[maxn];int p[25];int n,m,S;int ans;struct node{ int to,next;}s[maxn*10];void add(int u,int v){ s[cnt] = (node){v,head[u]}; head[u] = cnt++;}void dfs(int u,int deep){ bool flag = true; for(int i=0;i<deep;i++){ if(!mapp[u][p[i]]){ flag = false; break; } } if(flag){ p[deep++] = u; // printf("%d %d\n",flag,deep); if(deep == S){ ans++; return ; } } else return ; for(int i = head[u]; ~i ; i = s[i].next){ int to = s[i].to; if(vis[to]) continue; vis[to] = true; dfs(to,deep); vis[to] = false; }}void solve(){ Fill(vis,0); Fill(mapp,0); cnt = 0; Fill(head,-1); Fill(p,0); scanf("%d%d%d",&n,&m,&S); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); if(u > v) swap(u,v); //建有序有向边 add(u,v); mapp[u][v] = mapp[v][u] = 1; //双向标记 } ans = 0; for(int i=1;i<=n;i++){ vis[i] = true; dfs(i,0); vis[i] = false; } printf("%d\n",ans);}
阅读全文
0 0