题解 P1640 【[SCOI2010]连续攻击游戏】
是的,我来解释一下二分图的建图:
每件装备只能用一次,如果把攻击序列建成点,就是装备和攻击顺序的匹配。
比如属性值是3和5,那么这件装备要么在3位置要么在5位置被使用。
当然,按攻击顺序开始匹配,一旦匹配不成功,根据题意就必须中止。
还有,每次memset太慢了,用时间戳id。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 1010000
#define MAXM 4040000
#define X(n) (n+10000)
struct Edge
{
int to,nex;
Edge(){}
Edge(int _to, int _nex):to(_to),nex(_nex){}
};
Edge e[MAXM+5];
int first[MAXN+5], book[MAXN+5], match[MAXN+5], N, tot, id, op;
void Add(int a, int b)
{
e[tot] = Edge(b,first[a]);
first[a] = tot++;
return;
}
bool DFS(int x)
{
for(register int u = first[x], v; u+1; u = e[u].nex)
if(book[v=e[u].to]-id)
{
book[v] = id;
if(!match[v] || DFS(match[v]))
{
match[x] = v, match[v] = x;
return true;
}
}
return false;
}
int Hungary()
{
int ans = 0;
for(register int i = id = 1; i <= 10000; i++, id++)
if(DFS(i))
ans++;
else
break;
return ans;
}
int main()
{
scanf("%d",&N), memset(first,-1,sizeof(first));
for(register int i = 1, j; i <= N; i++)
for(j = 0; j < 2; j++)
scanf("%d",&op), Add(op,X(i)), Add(X(i),op);
printf("%d\n",Hungary());
return 0;
}