[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最多能连续攻击的次数。
输入输出样例
说明
Limitation
对于30%的数据,保证N < =1000
对于100%的数据,保证N < =1000000
转化成二分图的模型,左边是武器的属性值,右边是人
因为属性值是从一开始的,所以可以从1开始寻找匹配,知道找不到匹配就退出
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 #define LL long long 6 7 using namespace std; 8 9 const int MAXN = 1e6 + 10; 10 11 int N; 12 int id = 1; 13 int cnt = 0; 14 int match[MAXN]; 15 int vis[MAXN]; 16 int head[MAXN]; 17 18 struct edge { 19 int v, next; 20 } g[MAXN * 20]; 21 22 void addedge(int u, int v) 23 { 24 g[++cnt].next = head[u]; 25 g[cnt].v = v; 26 head[u] = cnt; 27 } 28 29 bool find_path(int x) 30 { 31 for(int j = head[x]; j; j = g[j].next) { 32 int to = g[j].v; 33 if((vis[to] - id)== 0) { 34 continue; 35 } 36 vis[to] = id; 37 if(!match[to] || find_path(match[to])) { 38 match[x] = to; 39 match[to] = x; 40 return true; 41 } 42 } 43 return false; 44 } 45 inline LL read() 46 { 47 LL x = 0, w = 1; char ch = 0; 48 while(ch < '0' || ch > '9') { 49 if(ch == '-') { 50 w = -1; 51 } 52 ch = getchar(); 53 } 54 while(ch >= '0' && ch <= '9') { 55 x = x * 10 + ch - '0'; 56 ch = getchar(); 57 } 58 return x * w; 59 } 60 61 int main() 62 { 63 N = read(); 64 for(int i = 1; i <= N; i++) { 65 int a = read(), b = read(); 66 addedge(a, i + 2 * N); 67 addedge(i + 2 * N, a); 68 addedge(b, i + 2 * N); 69 addedge(i + 2 * N, b); 70 } 71 for(int i = 1; i <= N; i++, id++) { 72 if(!find_path(i)) { 73 printf("%d\n", i - 1); 74 return 0; 75 } 76 } 77 printf("%d\n", N); 78 return 0; 79 }