bzoj1854 [Scoi2010]游戏——匈牙利算法

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1854

这题...据说可以用并查集做,但没有去看...

用二分图匹配的话,就把装备和它的两个属性连边,再从属性开始从小到大进行匈牙利算法;

这样可以保证匹配这个属性时先确保前面的都匹配成功了;

所以遇到无法匹配的情况时就结束了,输出即可;

小心TLE,所以避免 memset。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=1000005,maxm=10005;
int n,head[maxm],ct,pre[maxn],mx,ans;
int vis[maxn];
struct N{
    int to,next;
    N(int t=0,int n=0):to(t),next(n) {}
}edge[maxn<<1];
void add(int x,int y){edge[++ct]=N(y,head[x]); head[x]=ct;}
bool dfs(int x)
{
    for(int i=head[x],u;i;i=edge[i].next)
    {
        if(vis[u=edge[i].to]!=ans)
//        if(!vis[u=edge[i].to])//TLE!
        {
            vis[u]=ans;
            if(!pre[u]||dfs(pre[u]))
            {
                pre[u]=x; return 1;
            }
        }
    }
    return 0;
}
int main()
{
    scanf("%d",&n);
    for(int i=1,x,y;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,i); add(y,i);
        mx=max(mx,max(x,y));
    }
    for(int i=1;i<=mx;i++)
    {
//        memset(vis,0,sizeof vis);//TLE!
        ans++;
        if(!dfs(i))
        {
            printf("%d\n",ans-1); return 0;
        }
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-06-21 11:34  Zinn  阅读(104)  评论(0编辑  收藏  举报