【SCOI2010】【二分图最大匹配】游戏

来源:互联网 发布:windows屏保 编辑:程序博客网 时间:2024/06/08 16:08

这道题很明显的二分图模型,但是建图是关键。

将一件武器的两个属性看作二分图左边的点,然后把这两个点与要攻击的点连两条边。

这样原问题就转化为了在一个二分图上从小到大地找增广路,一旦未找到增广路,那此时的匹配数即位最大攻击的次数。

代码(Ps:使用了bitsit)

#include<cstdio>#include<bitset>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1000000 + 10;struct pnode{int d;pnode *next;pnode(){}pnode(int d,pnode *next):d(d),next(next){}}*first[maxn],__[maxn<<1],*tot = __;bool flag[maxn];int match[maxn];bitset <maxn> marked;int n,limit = 0;void init(){freopen("bzoj1854.in","r",stdin);freopen("bzoj1854.out","w",stdout);}void readdata(){scanf("%d",&n);for(int i = 1;i <= n;i++){int x,y;scanf("%d%d",&x,&y);limit = max(limit,x);limit = max(limit,y);first[x] = new(tot++)pnode(i,first[x]);first[y] = new(tot++)pnode(i,first[y]);}}bool crosspath(int u){for(pnode *p = first[u];p != NULL;p = p -> next){int v = p -> d;if(!marked.test(v)){marked.set(v);if(!match[v] || crosspath(match[v])){match[v] = u;return true;}}}return false;}void solve(){memset(match,0,sizeof(match));int ans = 0;for(int i = 1;i <= limit;i++){marked.reset();if(crosspath(i))ans++;else break;}printf("%d",ans);}int main(){init();readdata();solve();return 0;}




原创粉丝点击