[SCOI2010]连续攻击游戏 题解

[SCOI2010]连续攻击游戏 题解

题目地址:洛谷:【P1640】[SCOI2010]连续攻击游戏 – 洛谷、BZOJ:Problem 1854. — [Scoi2010]游戏

题目描述

lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次?

输入输出格式

输入格式:
输入的第一行是一个整数N,表示lxhgww拥有N种装备接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值

输出格式:
输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。

输入输出样例

输入样例#1:

3
1 2
3 2
4 5

输出样例#1:

2

说明

Limitation
对于30%的数据,保证N < =1000
对于100%的数据,保证N < =1000000
来源:SCOI 2010

题解

对装备和属性的值分别建点,从两个属性的值向装备连有向边,跑匈牙利算法匹配即可,注意我们枚举属性的值的时候,遇到某个值无法被匹配,则直接返回答案,因为要求连续攻击。
n很大,vis数组memset会TLE,我们可以换种方法,使用vis时间戳,每次dfs使用不同的时间戳就可以达到vis的效果。

代码

// Code by KSkun, 2018/5
#include <cstdio>
#include <cctype>
#include <cstring>

#include <algorithm>
#include <vector>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline LL readint() {
    register LL res = 0, neg = 1;
    register char c = fgc();
    while(!isdigit(c)) {
        if(c == '-') neg = -1;
        c = fgc();
    }
    while(isdigit(c)) {
        res = (res << 1) + (res << 3) + c - '0';
        c = fgc();
    }
    return res * neg;
}

const int MAXN = 1010005;

int n;

struct Edge {
    int to, nxt;
} gra[MAXN << 1];
int head[MAXN], tot;

inline void addedge(int u, int v) {
    gra[tot] = Edge {v, head[u]}; head[u] = tot++;
}

int vis[MAXN];
int match[MAXN];

inline bool dfs(int u, int clk) {
    for(int i = head[u]; ~i; i = gra[i].nxt) {
        int v = gra[i].to;
        if(vis[v] != clk) {
            vis[v] = clk;
            if(match[v] == -1 || dfs(match[v], clk)) {
                match[v] = u; match[u] = v; return true;
            }
        }
    }
    return false;
}

inline int bmatch() {
    int res = 0;
    memset(match, -1, sizeof(match));
    for(int i = 1; i <= 10000; i++) {
        if(match[i] == -1) {
            if(dfs(i, i)) res++;
            else break;
        }
    }
    return res;
}

int a, b;

int main() {
    memset(head, -1, sizeof(head));
    n = readint();
    for(int i = 1; i <= n; i++) {
        a = readint(); b = readint();
        addedge(a, i + 10000);
        addedge(b, i + 10000);
    }
    printf("%d", bmatch());
    return 0;
}


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据