lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次?
输入:
3
1 2
3 2
4 5
输出:
2
初次看的时候,想用装备建图模型,可以接在连续用的装备建一条边,然后这个模型似乎不太适用于二分图,当时想了一个有向图最长路的解法(未实现),但不能访问过去已经访问过的点,而新的起点又要把前面的标记清0,觉得不好下手,遂放弃。
仔细读题,发现攻击值的范围只有10000,想到一个模型,用装备连边到攻击数值,开一个1000000的容器用来存装备,建边,要保证1一定被匹配,但发现好像不太能保证1一定被匹配,且匹配不一定是连续的。
反过来,用数值建边到装备,因为匈牙利算法是一个连续的过程,我们从1开始匹配,如果能找到装备可以匹配就匹配,如果找不到了,就直接break。这是正解模型
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+10;
int n,x,y,used[100 * maxn],cy[100 * maxn];
vector<int> g[maxn];
int find(int u){
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if(!used[v]){
used[v] = 1;
if(!cy[v] || find(v)){
cy[v] = u;
return 1;
}
}
}
return 0;
}
int match(){
int res = 0;
for(int i = 1; i <= 10000; i++){
if(find(i)) res++;
else break;
}
return res;
}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d%d",&x,&y);
g[x].push_back(i);
g[y].push_back(i);
}
printf("%d\n",match());
return 0;
}