題意:給出200個數,選出最大的子集,使得子集中的數相互不整除。
解法:將可以整除的點連邊,看上去像是個無向圖最大獨立集,通過求最大團的辦法求解複雜度hold不住。於是觀察圖的特點,由於整除是一種偏序關係,因此構成的是一個有向無環圖,因此也是個二分圖(二分圖的一個充分必要條件是無奇圈),於是可以轉化爲求解二分圖的最大獨立集。具體做法Matrix67給出了證明過程,這篇文章裏有http://blog.csdn.net/kksleric/article/details/7465804。
public class Main {
int maxn = 210, maxm = 40010;
class node {
int be, ne;
node(int b, int e) {
be = b;
ne = e;
}
}
class Edmonds {
int E[] = new int[maxn], n, m, len;
node buf[] = new node[maxm];
int link[] = new int[maxn];
boolean vis[] = new boolean[maxn];
void init(int n, int m) {
this.m = m;
this.n = n;
len = 0;
Arrays.fill(E, -1);
}
void add(int a, int b) {
buf[len] = new node(b, E[a]);
E[a] = len++;
}
boolean find(int a) {
for (int i = E[a]; i != -1; i = buf[i].ne) {
int b = buf[i].be;
if (vis[b])
continue;
vis[b] = true;
if (link[b] == -1 || find(link[b])) {
link[b] = a;
return true;
}
}
return false;
}
int solve() {
Arrays.fill(link, -1);
int ans = 0;
for (int i = 1; i <= n; i++) {
Arrays.fill(vis, false);
if (find(i))
ans++;
}
return ans;
}
boolean cv[] = new boolean[maxn + maxn];
void cover() {// 求解最小覆蓋集
Arrays.fill(cv, false);
for (int i = 1; i <= m; i++)
if (link[i] == -1)
cv[n + i] = true;
boolean end = false;
while (!end) {
end = true;
for (int i = 1; i <= n; i++) {
if (cv[i])
continue;
boolean flag = false;
for (int j = E[i]; j != -1; j = buf[j].ne) {
int b = buf[j].be;
flag |= cv[b + n];
}
if (!flag)
continue;
cv[i] = true;
end = false;
for (int j = 1; j <= m; j++)
if (link[j] == i)
cv[j + n] = true;
}
}
for (int i = 1; i <= m; i++)
cv[i + n] = !cv[i + n];
}
}
Scanner scan = new Scanner(System.in);
Edmonds hun = new Edmonds();
int arr[] = new int[maxn], ans[] = new int[maxn];
void run() {
int n = scan.nextInt();
int m = scan.nextInt();
hun.init(n, n);
while (m-- > 0) {
int a = scan.nextInt();
int b = scan.nextInt();
hun.add(Math.min(a, b), Math.max(a, b));
}
int res = n - hun.solve();
System.out.println(res);
hun.cover();
for (int i = 1; i <= n; i++)
if (!hun.cv[i] && !hun.cv[i + n]) {
if (--res > 0)
System.out.print(i+ " ");
else
System.out.println(i);
}
}
public static void main(String[] args) throws IOException {
new Main().run();
}
}