TJOI2018 d1t2 智力竞赛

题意不太明确......

这题的n需要一上来就+1。就是求一个可交最小路径覆盖,二分答案即可。

不知道为什么我的常数那么大,别人几乎300ms就完事了,我需要800ms。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline char gc() {  
    static char now[1<<16], *S, *T;  
    if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}  
    return *S++;  
}
inline int read() {  
    int x = 0; char c = gc();  
    while(c < '0' || c > '9') c = gc();  
    while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();}  
    return x;  
}
inline void print(int x) {  
    if(!x) {puts("0"); return ;}  
    int dgt[20], now = 0;  
    while(x) {dgt[++now] = x % 10; x/= 10;}  
    for(; now; --now) putchar('0' + dgt[now]); puts("");  
}
int n, m, f[510][510], v[510], b[510]; bool can[510];
int match[510], vis[510];
bool dfs(int x) {
    for(int i = 1; i <= m; ++i) {
        if(can[i] && f[x][i] && !vis[i]) {
            vis[i] = 1;
            if(!match[i] || dfs(match[i])) {match[i] = x; return true;}
        }
    }
    return false;
}
inline int check(int tot) {
    int res = 0; memset(match, 0, sizeof(match));
    for(int i = 1; i <= m; ++i) {
        memset(vis, 0, sizeof(vis));
        if(can[i] && dfs(i)) ++res;
        if(tot - res <= n + 1) return tot - res;
    }
    return tot - res;
}
int main() {
    n = read(); m = read();
    for(int i = 1; i <= m; ++i) {
        v[i] = read(); int num = read(); can[i] = 1;
        for(int j = 1; j <= num; ++j) f[i][read()] = 1;
    }
    for(int k = 1; k <= m; ++k)
        for(int i = 1; i <= m; ++i)
            for(int j = 1; j <= m; ++j) f[i][j]|= f[i][k] & f[k][j];
    memcpy(b, v, sizeof(b)); sort(b+1, b+m+1); b[m + 1] = 1e9 + 1;
    int l = 1, r = m + 1, ans = 0;
    while(l <= r) {
        int mid = (l + r)>>1; mid = b[mid]; int sum = 0;
        for(int i = 1; i <= m; ++i) if(v[i] >= mid) can[i] = 0; else ++sum;
        if(check(sum) <= n + 1) {ans = mid; l = mid + 1;}
        else r = mid - 1;
        for(int i = 1; i <= m; ++i) can[i] = 1;
    }
    if(ans == 1e9 + 1) puts("AK");
    else print(ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/richard_for_oi/article/details/80330258
今日推荐