[UVA] 11065 - A Gentlemen's Agreement
A Gentlemen's Agreement
|
問一次最多同時維修多少紅綠燈,以及不可擴充的方案。
(問最大獨立集 S 的 |S| = ? 以及不可擴充增點的獨立集個數)
首先是 DJWS 拿下 Rank 1,我仔細思考了一下,很想隨機化追上去,
但似乎沒那麼簡單。這題一定是 NP-complete problem,甭想了。
點數最多 60 個,看到這數字直接聯想到位元運算,對於所有排斥檢查時使用 XOR 或者是 AND 去做計算,盡可能地減少進位的消耗時間,同時也捨去掉迴圈的 branch,只拿下 Rank 20。
#include <stdio.h>
#include <iostream>
using namespace std;
typedef unsigned long long LL;
unsigned long long g[65];
int hash[10008] = {};
int mx, special, n;
void dfs(LL state, int ch, LL mark, LL noch) {
//printf("%lld %d\n", state.v, ch);
if(state == 0) {
if(mx < ch)
mx = ch;
if(mark == (1LL<<n)-1)
special++;
return;
}
LL lowbit = state&(-state);
int idx = hash[lowbit%10007];
//printf("lowbit %lld idx %d\n", lowbit, idx);
LL tmp = state;
tmp = tmp ^ (tmp&g[idx]);
dfs(tmp, ch+1, mark|g[idx], noch);
tmp = state ^ lowbit;
dfs(tmp, ch, mark, noch|lowbit);
}
int main() {
int testcase;
int m, x, y;
int i, j, k;
for(i = 0; i < 63; i++) {
if(hash[(1LL<<i)%10007])
puts("ERR");
hash[(1LL<<i)%10007] = i;
}
scanf("%d", &testcase);
while(testcase--) {
scanf("%d %d", &n, &m);
for(i = 0; i < n; i++)
g[i] = 1LL<<i;
while(m--) {
scanf("%d %d", &x, &y);
g[x] |= 1LL<<y;
g[y] |= 1LL<<x;
}
LL state;
state = (1LL<<n)-1;
mx = 1, special = 0;
dfs(state, 0, 0, 0);
printf("%d\n%d\n", special, mx);
}
return 0;
}