[bzoj1854][SCOI2010]游戏

Description

一个装备有两个属性,一个装备只能被使用一次,一次使用一种属性。攻击\(boss\)时需按属性\(1\)、属性\(2\)、属性\(3\)...属性\(k\)的顺序使用,问\(k\)最大为多少。

Input

输入的第一行是一个整数\(N\),表示有\(N\)种装备。接下来\(N\)行,是对这\(N\)种装备的描述,每行\(2\)个数字,表示第\(i\)种装备的\(2\)个属性值。

Output

输出一行,包括\(1\)个数字,表示\(k\)

Sample Input

3
1 2
3 2
4 5

Sample Output

2

HINT

\(1\;\leq\;\)属性值\(\;\leq\;10000,N\;\leq\;1000000\).

Solution

由于一种装备只能使用一次,而且只有装备和属性值两种分类,就会想到二分图匹配。

将装备和属性值分成两个集合,将属性值向所属装备连一条边,判断当前\(k\),如果可匹配,判断\(k+1\),如果不可行,\(k-1\)就是答案。

如果使用匈牙利算法的话,\(used[\;]\)不能每次都重新赋值\(false\),会\(T\)(实测),而要将当前\(k\)作为判断标志(\(used[\;]=k\)为访问过)。

#include<set> 
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define K 10001
#define N 1000001
#define M 2000001
using namespace std;
struct graph{
    int nxt,to;
}e[M];
int g[K],u[N],fr[N],n,cnt,ans;
inline int read(){
    int ret=0;char c=getchar();
    while(!(c>='0'&&c<='9'))
        c=getchar();
    while(c>='0'&&c<='9'){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret;
}
inline void addedge(int x,int y){
    e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline bool match(int k){
    for(int i=g[k];i;i=e[i].nxt)
        if(u[e[i].to]!=ans){
            u[e[i].to]=ans;
            if(!fr[e[i].to]||match(fr[e[i].to])){
                fr[e[i].to]=k;return true;
            }
        }
    return false;
}
inline void init(){
    n=read();
    for(int i=1,k;i<=n;i++){
        k=read();addedge(k,i);
        k=read();addedge(k,i);
    }
    for(ans=1;ans<K;ans++){
        if(!match(ans)) break;
    }
    printf("%d\n",--ans);
}
int main(){
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    init();
    fclose(stdin);
    fclose(stdout);
    return 0; 
}
posted @ 2016-07-09 17:40  Aireen_Ye  阅读(178)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.