[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<=属性值<=10000,N < =1000000

Solution

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

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

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

 1 #include<set> 
 2 #include<cmath>
 3 #include<ctime>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<vector>
 8 #include<cstring>
 9 #include<cstdlib>
10 #include<iostream>
11 #include<algorithm>
12 #define K 10001
13 #define N 1000001
14 #define M 2000001
15 using namespace std;
16 struct graph{
17     int nxt,to;
18 }e[M];
19 int g[K],u[N],fr[N],n,cnt,ans;
20 inline int read(){
21     int ret=0;char c=getchar();
22     while(!(c>='0'&&c<='9'))
23         c=getchar();
24     while(c>='0'&&c<='9'){
25         ret=ret*10+c-'0';
26         c=getchar();
27     }
28     return ret;
29 }
30 inline void addedge(int x,int y){
31     e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
32 }
33 inline bool match(int k){
34     for(int i=g[k];i;i=e[i].nxt)
35         if(u[e[i].to]!=ans){
36             u[e[i].to]=ans;
37             if(!fr[e[i].to]||match(fr[e[i].to])){
38                 fr[e[i].to]=k;return true;
39             }
40         }
41     return false;
42 }
43 inline void init(){
44     n=read();
45     for(int i=1,k;i<=n;i++){
46         k=read();addedge(k,i);
47         k=read();addedge(k,i);
48     }
49     for(ans=1;ans<K;ans++){
50         if(!match(ans)) break;
51     }
52     printf("%d
",--ans);
53 }
54 int main(){
55     freopen("game.in","r",stdin);
56     freopen("game.out","w",stdout);
57     init();
58     fclose(stdin);
59     fclose(stdout);
60     return 0; 
61 }

 

 

原文地址:https://www.cnblogs.com/AireenYe/p/5656287.html