题目链接
https://www.luogu.com.cn/problem/P1640
思路
因为每件装备只能用一次,如果把攻击序列建成点,则本题可以看成是装备和攻击顺序的二分图匹配,因此可以采用匈牙利算法进行求解。
本题的属性值最大为
1
e
4
1e4
1e4,范围有点大,用
m
e
m
s
e
t
memset
memset会超时。因此我们可以打上一个时间戳来避免超时。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5, M = 2e6 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, now;
int chk[N], match[N];
struct Edge
{
int to, next;
} edge[M];
int head[N], idx;
void init()
{
memset(head, -1, sizeof head);
idx = 0;
}
void add_edge(int u, int v)
{
edge[idx].to = v;
edge[idx].next = head[u];
head[u] = idx++;
}
bool find(int u)
{
for (int i = head[u]; i != -1; i = edge[i].next)
{
int ver = edge[i].to;
if (chk[ver] != now)
{
chk[ver] = now;
if ((match[ver] == -1) || find(match[ver]))
{
match[ver] = u;
return true;
}
}
}
return false;
}
void solve()
{
cin >> n;
init();
memset(match, -1, sizeof match);
for (int i = 1, a, b; i <= n; i++)
{
cin >> a >> b;
add_edge(a, i);
add_edge(b, i);
}
int ans = 0;
for (int i = 1; i <= 1e4; i++)
{
now++;//时间戳
if (find(i)) ans++;
else break;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}