bzoj1854 [Scoi2010]游戏 ([SCOI2010]连续攻击游戏)

bzoj1854 [Scoi2010]游戏 ([SCOI2010]连续攻击游戏)


据说正解是并查集???我不会
这不是一道匈♂牙利好题吗???
一个装备的两个属性都向它连边,然后跑一遍匈♂牙利
注意:

  • 匈♂牙利要从1开始一个一个匹配,不行了直接break
  • 我蠢了忘了匈♂牙利的优化。。。匈♂牙利是每次更新vis,然后跑一遍,更新的复杂度巨大。。。所以按照时间打标记判断vis改成和时间比较

(手动艾特iot;搞了个匈♂牙利水题合集,就三道。。。你也不放10+道,两道我以前切过233333)
(mdzz数组开小WA我两次)


Code

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#define Fname "game"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0;rg bool flg=0;rg char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return flg?-x:x;
}
int n;
const int maxn=10010,maxm=1000100;
int fir[maxn],dis[maxm<<1],nxt[maxm<<1],id;
il vd add(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
int match[maxm],vis[maxm],ans;
il bool dfs(int x){
    erep(i,x)if(ans^vis[dis[i]]){
        vis[dis[i]]=ans;
        if(match[dis[i]]==-1||dfs(match[dis[i]]))
            {match[dis[i]]=x;return 1;}
    }return 0;
}
int main(){
#ifdef xzz
    freopen(Fname".in","r",stdin);
    freopen(Fname".out","w",stdout);
#endif
    n=gi();
    rep(i,1,n)add(gi(),i),add(gi(),i),match[i]=-1;
    ans=0;
    while(1){
        ++ans;
        if(!dfs(ans))break;
    }printf("%d\n",ans-1);
    return 0;
}
posted @ 2017-10-03 22:39  菜狗xzz  阅读(317)  评论(1编辑  收藏  举报