[Codeforces Round #428 DIV2E (CF839E)] Mother of Dragons
2017-08-13 23:19
471 查看
题意
给出n≤40个点的邻接矩阵,要求给每个点赋值,使得点的权值和为K,每条边权值为两端点点权的乘积,最大化边的权值和。题解
这道题我不会严谨的证明,只能猜一猜,官方题解http://codeforces.com/blog/entry/53815。首先假如整个图是一个点数为k的团,那么每个点的权值分为K/k,最优答案将是K2(k−1)2k。
假如图中存在一个点数为k的团和一个点数为k+1的团,由(k−1)2k=12−12k知,选择k+1的团答案更优。
若存在一个点数为k的团,和差一条边就是k+1的团的伪团(即k+1个点,(k+1)k2−1条边,暂时称作伪团),若给k+1的伪团每点赋值Kk+1,则可以通过做差法求得伪团不如k点的团更优。
基于以上结果,猜测答案取得最优时即为点集为最大团时。
下面就是求最大团的过程了。
由于一般图求最大团是NP-hard的,做的求最大团的题目,只做过2n的搜索。这道题目点数40,显然是双向搜索。于是写了这道题的代码1
436 ms。
然而打开status一看,尽是15ms 30ms的代码,于是点开某30ms代码学习,发现了一个没接触过的搜索算法Bron−Kerbosch,于是在网上学习了一下这个算法的姿势,发现朴素的Bron−Kerbosch算法是求所有的极大团,可以求出最大团,但通过一些优化只求最大团可以有效的提高效率。其中两种优化较好,第一种优化是按照退化序枚举点的优化,也就是不断向点集中添点后求最大团,按照这个算法写了代码2
15ms;第二种是带轴优化,对于一个与当前团内点有边相连但不在当前团内的点u,最大团要么包含u,要么包含与u不相邻的其他点,即选定u后将备选点中与u相邻的点都删去(因为备选点是与当前团中点都相邻的点,如果某备选点与u相邻且被选中,那么必定也要u),所以只需要检验点u与和u不相邻的点即可,根据这个思想写了代码3
15ms。
参考资料:
https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm
https://wenku.baidu.com/view/65972e184693daef5ff73d2c.html
http://www.cnblogs.com/yefeng1627/archive/2013/03/31/2991592.html
代码1
/// by ztx /// blog.csdn.net/hzoi_ztx #include <bits/stdc++.h> #define Rep(i,l,r) for(i=(l);i<=(r);i++) #define rep(i,l,r) for(i=(l);i< (r);i++) #define Rev(i,r,l) for(i=(r);i>=(l);i--) #define rev(i,r,l) for(i=(r);i> (l);i--) #define Each(i,v) for(i=v.begin();i!=v.end();i++) #define r(x) read(x) typedef long long ll ; typedef double lf ; int CH , NEG ; template <typename TP>inline void read(TP& ret) { ret = NEG = 0 ; while (CH=getchar() , CH<'!') ; if (CH == '-') NEG = true , CH = getchar() ; while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ; if (NEG) ret = -ret ; } #define kN 45LL #define kS 1048576LL int n, mid, cnt[kN]; bool g[kN][kN]; bool okL[kS], okR[kS]; int siz[kS]; void dfsL(int p=0,int s=0) { if (p == mid) return; dfsL(p+1,s); if (s) for(int i=0;i<mid;i++) if ((s&(1<<i)) && !g[p][i]) return; s |= (1<<p); okL[s] = true; dfsL(p+1,s); } void dfsR(int p=mid,int s=0) { if (p == n) return; dfsR(p+1,s); if (s) for(int i=mid;i<n;i++) if ((s&(1<<i-mid)) && !g[p][i]) return; s |= (1<<p-mid); okR[s] = true; dfsR(p+1,s); } int calc(int s) { int i,ret=0; rep (i,0,mid) if (s&(1<<i)) ret ++ ; return ret; } int main() { int i, j, k, K, ma, sz; lf ans; r(n), r(K); if (n == 1) {puts("0"); goto END; } rep (i,0,n) rep (j,0,n) r(g[i][j]); mid = n>>1; dfsL(); dfsR(); ma = 0; for (i = (1<<mid)-1; i >= 0; i -- ) if (okL[i]) siz[i] = calc(i); for (i = 0; i < (1<<mid); i ++ ) if (siz[i]) { if (siz[i] > ma) ma = siz[i]; rep (j,0,mid) if (!(i&(1<<j))) { k = i|(1<<j); if (siz[k] < siz[i]) siz[k] = siz[i]; } } for (i = (1<<n-mid)-1; i >= 0; i -- ) if (okR[i]) { sz = 0; rep (j,0,mid) cnt[j] = 0; rep (j,mid,n) if (i&(1<<j-mid)) { sz ++ ; rep (k,0,mid) if (g[j][k]) cnt[k] ++ ; } k = 0; rep (j,0,mid) if (cnt[j] == sz) k |= (1<<j); if (siz[k]+sz > ma) ma = siz[k]+sz; } ans = 1.0*K*K*(ma-1)/ma/2.0; printf("%.12lf\n", ans); END: getchar(), getchar(); return 0; }
代码2
/// by ztx /// blog.csdn.net/hzoi_ztx #include <bits/stdc++.h> #define Rep(i,l,r) for(i=(l);i<=(r);i++) #define rep(i,l,r) for(i=(l);i< (r);i++) #define Rev(i,r,l) for(i=(r);i>=(l);i--) #define rev(i,r,l) for(i=(r);i> (l);i--) #define Each(i,v) for(i=v.begin();i!=v.end();i++) #define r(x) read(x) typedef long long ll ; typedef double lf ; int CH , NEG ; template <typename TP>inline void read(TP& ret) { ret = NEG = 0 ; while (CH=getchar() , CH<'!') ; if (CH == '-') NEG = true , CH = getchar() ; while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ; if (NEG) ret = -ret ; } #define kN 45LL int n; namespace MaxClique { bool g[kN][kN]; int ans, adj[kN][kN], ma[kN]; bool dfs(int now,int dep) { int i, j, u, v, poi; rep (i,0,now) { if (dep+now-i <= ans) return false; u = adj[dep][i], poi = 0; if (dep+ma[u] <= ans) return false; // rec[dep] = u; rep (j,i+1,now) if (v=adj[dep][j], g[u][v]) adj[dep+1][poi++] = v; if (dfs(poi,dep+1)) return true; } if (dep > ans) { ans = dep; // upd max clique return true; } return false; } int work() { int i, j, poi; ans = 0; Rev (i,n-1,0) { poi = 0; rep (j,i+1,n) if (g[i][j]) adj[1][poi++] = j; //rec[0] = i; dfs(poi,1); ma[i] = ans; } return ans; } } int main() { int K, i, j; lf ans; r(n), r(K); using MaxClique::g; using MaxClique::work; rep (i,0,n) rep (j,0,n) r(g[i][j]); i = work(); ans = 1.0*K*K*(i-1)/i/2.0; printf("%.12lf\n", ans); END: getchar(), getchar(); return 0; }
代码3
/// by ztx /// blog.csdn.net/hzoi_ztx #include <bits/stdc++.h> #define Rep(i,l,r) for(i=(l);i<=(r);i++) #define rep(i,l,r) for(i=(l);i< (r);i++) #define Rev(i,r,l) for(i=(r);i>=(l);i--) #define rev(i,r,l) for(i=(r);i> (l);i--) #define Each(i,v) for(i=v.begin();i!=v.end();i++) #define r(x) read(x) typedef long long ll ; typedef double lf ; int CH , NEG ; template <typename TP>inline void read(TP& ret) { ret = NEG = 0 ; while (CH=getchar() , CH<'!') ; if (CH == '-') NEG = true , CH = getchar() ; while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ; if (NEG) ret = -ret ; } #define kN 45LL int n; namespace MaxClique { using std::max; typedef unsigned long long U; inline int ctz(U s){return s?__builtin_ctzll(s):8*sizeof(U);} int ans; bool g[kN][kN]; U N[kN]; void dfs(U R,U P,U X) { if (!P && !X) { ans = max(ans,__builtin_popcountll(R)); return ; } if (!P) return; int pivot = ctz(P|X); U PP = P&~N[pivot]; for(int u=ctz(PP);u<n;u+=ctz(PP>>(u+1))+1) { dfs(R|((U)1<<u),P&N[u],X&N[u]); P ^= ((U)1<<u), X |= ((U)1<<u); } } int work() { int i, j; rep (i,0,n) rep (j,0,n) if (g[i][j]) N[i]^=(U)1<<j; dfs(0,((U)1<<n)-1,0); return ans; } } int main() { int K, i, j; lf ans; r(n), r(K); using MaxClique::g; using MaxClique::work; rep (i,0,n) rep (j,0,n) r(g[i][j]); i = work(); ans = 1.0*K*K*(i-1)/i/2.0; printf("%.12lf\n", ans); END: getchar(), getchar(); return 0; }
相关文章推荐
- Codeforces Round #428 (Div. 2) E. Mother of Dragons
- 【CF839E】Mother of Dragons 折半状压
- (最大团)Codeforces Round #428 (Div. 2) E. Mother of Dragons
- Codeforces Round #428 (Div. 2) E - Mother of Dragons
- codeforces 839 E. Mother of Dragons(最大团)
- Codeforces Codeforces Round #432 (Div. 2 D ) Arpa and a list of numbers
- use css modify the sub object of a div
- Codeforces Round #433 (Div. 2, based on Olympiad of Metropolises)
- codeforces 251 div2 C. Devu and Partitioning of the Array 模拟
- Codeforces Round #342 (Div. 2)--B. War of the Corporations
- Codeforces Round #401 (Div. 2) D Cloud of Hashtags —— 串
- Codeforces Round #209 (Div. 2) D. Pair of Numbers
- Codeforces Round #437 (Div. 2 C. Ordering Pizza 贪心 only two types of pizza
- 【CS Round #48 (Div. 2 only)】Game of Chance
- Codeforces Round #398 (Div. 2) D. Cartons of milk —— 二分
- A. Case of the Zeros and Ones(Codeforces Round #310 (Div. 2) 栈)
- CF-Codeforces Round #392 (Div. 2)-A-Holiday Of Equality
- Codeforces Round #392 (Div. 2)A Holiday Of Equality
- Codeforces Round #410 (Div. 2) E. Mike and code of a permutation(拓扑序+线段树)
- Codeforces Round #428 (Div. 2) B.Game of the Rows(贪心)