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\n",--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 }
时间: 2024-12-24 04:56:42