poj2724

poj2724

今天考试又炸了呢。

正文

题目链接 其实题目描述的十分不清楚。我瞪了十分钟愣是没看题。。但是后面发现,这不就是一个二分图最大匹配吗!

我们只要统计出被感染的奶酪数,然后看最多可以操作几次带 ‘*’ 的,就好了这个机器的操作简直耐人寻味,可以把二进制里只有以以一位不同的一起做。

10min

这什么东西打暴力吧(笑

20min

这不是一个二分图最大匹配吗。干

30min

转完了二进制。。怎么判呀。稍微想了想,可以这样 对于两个数 A,B,如果 A^B = C 这个C只有一位是 1, 咋办 - 1 之后异或不就完了,然后就发现事实上还要判一下 C 是不是0

然后怎么匹配,我们还是要把图的二分呀。咋二分?

35min

想到了如何二分图 ,根据每一个数二进制一的个数来二分,我们显然的可以知道,如果一的个数奇偶,他们肯定一起操作不了。

40min

干呀,裸的匈牙利上呀!

60min

不错样例过了,交一发试试。 TLE 啥回事,匈牙利会 T ?? 然后看了下 wyq 的记录 1907ms ,嗯,被卡常了。。然后跟 Singer 说匈牙利T了,要换ISAP..就开始写ISAP

70min

正写着ISAP.瞥了眼原来代码。。数组开小了。开大点,再交一发 WA 开始Debug

75min

p数组忘清零了。。交一发。 AC

代码

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> 

#define get getchar
#define put putchar

int read() { int x = 0; bool f = 0; char ch = get(); while(ch < '0' || ch >'9') { f = (ch == '-'); ch = get(); }while(ch <= '9' && ch >= '0') { x = (x << 1) + (x << 3) + (ch - '0'); ch = get(); }return f ? -x : x; }
void write(int x) { if(x < 0) { put('-'); x = abs(x); }if(x < 10) { put(x + 48); return; }write(x / 10); put(x % 10 + 48); }

#undef put
#undef get

char get() {char ch = getchar(); while(ch == '\r' || ch == '\n' || ch == ' ') { ch = getchar(); } return ch; }

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

using namespace std;

const int Maxn = 11, Max = Maxn << 7;

int n, m, tmp, ops, cou[Max], num, ans, h[Max], cnt, p[Max], poi[Max];

char ch;

struct Edge {
    int to, lac;
    void insert(int x, int y) { to = y; lac = h[x]; h[x] = cnt++; }
}edge[Max * Max];

bool flag[Max];

bool find(int u) {
    for(int i = h[u]; i != -1; i = edge[i].lac) {
        int to = edge[i].to;
        if(flag[to]) { continue; }
        flag[to] = 1;
        if(!p[to] || find(p[to])) {
            p[to] = u;
            return 1;
        }
    }
    return 0;
}

bool ok(int i, int j) {
    int c = poi[i] ^ poi[j];
    return (c != 0) && !(c & (c-1));
}

int main() {
    freopen("test.in", "r", stdin);
    while(true) {
        n = read(); m = read(); ans = 0; cnt = 0;
        if(!n && !m) { break; }
        memset(flag, 0, sizeof flag);
        for(int i = 1; i <= m; ++i) {
            tmp = 0; ops = -1;
            for(int i = 1; i <= n; ++i) { ch = get(); if(ch == '*') { ops = n - i; } tmp = (tmp << 1) + ((ch == '*' || ch == '0') ? 0 : 1) ; }
            if(ops != -1) { flag[tmp] = 1; flag[tmp | (1 << ops)] = 1; }
            else { flag[tmp] = 1; }
        }
        num = 0;
        memset(cou, 0, sizeof cou);
        for(int i = 0, j; i < 1 << n; ++i)  { if(flag[i]) { poi[++num] = j = i ; while(j > 0) { cou[num] += (j & 1); j = j / 2; } } }
        /* 建边 1是奇数向 1是偶数的 */
        memset(h, -1, sizeof h);
        for(int i = 1; i <= num; ++i) {
            if(! (cou[i] & 1)) { continue; }
            for(int j = 1; j <= num; ++j) { if(! (cou[j] & 1) && ok(i, j)){ edge[cnt].insert(i, j); } }
        }
        memset(p, 0, sizeof p);
        for(int i = 1; i <= num; ++i) 
        { if(!(cou[i] & 1)) { continue; } memset(flag, 0, sizeof flag); if(find(i)) { ans++; } }
        write(num - ans); putchar('\n');
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhltao/p/12516568.html
今日推荐