P1640 [SCOI2010]连续攻击游戏

题目描述

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

输入输出格式

输入格式:

输入的第一行是一个整数N,表示lxhgww拥有N种装备接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值

输出格式:

输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。

输入输出样例

输入样例#1:
3
1 2
3 2
4 5
输出样例#1:
2

说明

对于30%的数据,保证N < =1000

对于100%的数据,保证N < =1000000


  

  其实我们这道题的思路很好想的啊。

当然是一种很不好做的思路。

  就是将两个属性分成左右部点,这时就会发现我们要处理只能用一次就不那么好办了。

  那么我们热动分析一下。

  再一下。

  然后。

正解就是

  所以我们考虑将对于物品 的属性 a,b ,分别从 a 和 b 向 i 连一条有向边。将物品的属性当做左部点,编号当做右部点,求最大匹配即可。


 
vis数组版

奉上代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int MA=1000001;
int n;
int head[MA],ecnt,pre[MA*10];
bool vis[MA];
struct ss{
    int to,nxt;
}t[MA*2];

void add(int a,int b) {
    t[++ecnt].nxt=head[a];
    t[ecnt].to=b;
    head[a]=ecnt;
    return;
}

bool dfs(int now) {
    if(vis[now]) return 0;
    vis[now]=1;
    for(int i=head[now];i;i=t[i].nxt) {
        if(!pre[t[i].to]||dfs(pre[t[i].to])) {
            pre[t[i].to]=now;
            return 1;
        }
    }
    return 0;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,i);
        add(b,i);
    }
    int ans=0;
    for(int i=1;i<=2*n;i++) {
        memset(vis,0,sizeof vis);
        if(dfs(i)) ans++;
        else break;
    }
    cout<<ans<<endl;
    return 0;
}
time优化vis

奉上代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int MA=1000001;
int n;
int head[MA],ecnt,pre[MA*10];
int vis[MA],tim;
struct ss{
    int to,nxt;
}t[MA*2];

void add(int a,int b) {
    t[++ecnt].nxt=head[a];
    t[ecnt].to=b;
    head[a]=ecnt;
    return;
}

bool dfs(int nw) {
    for(int i=head[nw];i;i=t[i].nxt) {
        if(vis[t[i].to]!=tim) {
            vis[t[i].to]=tim;
            if(!pre[t[i].to]||dfs(pre[t[i].to])) {
                pre[t[i].to]=nw;
                return true;
            }
        } 
    }
    return false;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,i);
        add(b,i);
    }
    int ans=0;
    for(int i=1;i<=10000;i++) {
        tim++;
        if(dfs(i)) ans++;
        else break;
    }
    printf("%d
",ans);
    return 0;
}

完成。

  谢谢。

原文地址:https://www.cnblogs.com/qxyzili--24/p/10620611.html