1. 程式人生 > >[luogu1640 SCOI2010]連續攻擊遊戲 (二分圖匹配)

[luogu1640 SCOI2010]連續攻擊遊戲 (二分圖匹配)

() oss ring ems put printf class names 表示

[傳送門] (https://www.luogu.org/problemnew/show/P1640)

Description

lxhgww最近迷上了一款遊戲,在遊戲裏,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多只能使用一次。遊戲進行到最後,lxhgww遇到了終極boss,這個終極boss很奇怪,攻擊他的裝備所使用的屬性值必須從1開始連續遞增地攻擊,才能對boss產生傷害。也就是說一開始的時候,lxhgww只能使用某個屬性值為1的裝備攻擊boss,然後只能使用某個屬性值為2的裝備攻擊boss,然後只能使用某個屬性值為3的裝備攻擊boss……以此類推。現在lxhgww想知道他最多能連續攻擊boss多少次?

Input

輸入的第一行是一個整數N,表示lxhgww擁有N種裝備接下來N行,是對這N種裝備的描述,每行2個數字,表示第i種裝備的2個屬性值

Output

輸出一行,包括1個數字,表示lxhgww最多能連續攻擊的次數。

Sample Input

3
1 2
3 2
4 5

Sample Output

2

HINT

對於30%的數據,保證N < =1000

對於100%的數據,保證N < =1000000

Solution

二分圖匹配 通過更改vis標記減少memset

Code

//By Menteur_Hxy
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;

int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=1000010;
int n,ans;
int vis[N],fr[N];
vector<int> V[N];

bool dfs(int x) {
    int siz=V[x].size();
    F(i,0,siz-1) {
        int v=V[x][i];
        if(vis[v]!=ans+1) {
            vis[v]=ans+1;
            if(!fr[v]||dfs(fr[v])) {
                fr[v]=x;
                return 1;
            }
        }
    }
    return 0;
}

int main() {
    n=read();
    F(i,1,n) {
        int x=read(),y=read();
        V[x].push_back(i);
        V[y].push_back(i);
    }
    F(i,1,10000) {
        if(!dfs(i)) break;
        ans++;
    }
    printf("%d\n",ans);
    return 0;
}

[luogu1640 SCOI2010]連續攻擊遊戲 (二分圖匹配)