给出一个具有N个结点的无向图,将其分成两个集合S1,S2. 这两个集合的点的个数一样多,但连接它们的边最少.
给出一个具有N个结点的无向图,将其分成两个集合S1,S2. 这两个集合的点的个数一样多,但连接它们的边最少.
第一行给出数字N,M,代表有N个点,M条边. 下面M行,每行两个数字代表此两点间有条边.
输出的点集应包含1,且按升序排列
N<=26
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <algorithm> #include <bitset> using namespace std; #define reg register #define gc getchar inline int read() { int res=0;char ch=gc();bool fu=0; while(!isdigit(ch)){if(ch==‘-‘)fu=1;ch=gc();} while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=gc(); return fu?-res:res; } int n, m; int bin[27], cb[1<<14]; int sit[29]; int ans = 1e9, ansS; int Count(int x) { return cb[x>>13] + cb[(bin[13] - 1) & x]; } void dfs(int lst, int s1, int s2, int now, int num) { if (num == n / 2) { if (now < ans) ans = now, ansS = s1; return ; } for (reg int i = lst ; i <= n ; i ++) { if (!(s2 & bin[i - 1])) continue; dfs(i + 1, s1 + bin[i - 1], s2 - bin[i - 1], now - Count(sit[i] & s1) + Count(sit[i] & s2), num + 1); } } int main() { n = read(), m = read(); bin[0] = 1; for (reg int i = 1 ; i <= 26 ; i ++) bin[i] = bin[i - 1] << 1; for (reg int i = 1 ; i < bin[13] ; i ++) cb[i] = cb[i >> 1] + (i & 1); for (reg int i = 1 ; i <= m ; i ++) { int x = read(), y = read(); sit[x] |= bin[y - 1]; sit[y] |= bin[x - 1]; } dfs(1, 0, bin[n] - 1, 0, 0); if (!(ansS & bin[0])) ansS = (bin[n] - 1) ^ ansS; for (reg int i = 1 ; i <= n ; i ++) if (ansS & bin[i - 1]) printf("%d ", i); return 0; }
[BZOJ1130] [POI2008]POD Subdivision of Kingdom
原文:https://www.cnblogs.com/BriMon/p/9785729.html