BZOJ1854:[SCOI2010]连续攻击游戏——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1854

https://www.luogu.org/problemnew/show/P1640

lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次?

莫名奇妙的就想到了一个模型,然后脑子瓦特了的情况下竟然写了个正解但是不会论证,emmm……

考虑过权值和权值建边(然而会有重编一定不行),物品和物品建边(显然你不知道属性值了一定不行)。

那就物品和权值建边,对于权值分别向物品连有向边然后跑匈牙利算法即可。

为什么呢?显然,当我们尝试去匹配第i个属性的时候,i-1已经匹配完毕,如果i不能匹配的话就跳出并且输出i-1即可。

(PS:bzoj玩家请注意,不要每次dfs清空vis数组因为这样时间复杂度就不对了,所以需要优化)

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000010;
const int M=10010;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int to,nxt;
}e[N*2];
int n,m,ans,cnt;
int shu[N],head[M],vis[N];
inline void add(int u,int v){
    e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
bool dfs(int u,int id){
    for(int i=head[u];i;i=e[i].nxt){
    int v=e[i].to;
    if(vis[v]!=id){
        vis[v]=id;
            if(!shu[v]||dfs(shu[v],id)){
                shu[v]=u;
                return 1;
            }
    }
    }
    return 0;
}
int main(){
    n=read();m=M-10;
    for(int i=1;i<=n;i++){
    add(read(),i);add(read(),i);
    }
    for(int i=1;i<=m;i++){
        if(dfs(i,i))ans++;
    else break;
    }
    printf("%d
",ans);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/8540220.html