• 洛谷P1640 [SCOI2010]连续攻击游戏


    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

    说明

    Limitation

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

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

    来源:SCOI 2010

    /*
        由于攻击所需属性是从1开始连续的,又只有n个武器,所以最多攻击n次,最大属性只需要考虑到n
        属性与武器是二分图的两个集合,属性与他对应的武器相连
        从属性为1的情况开始找匹配,直到找不到了就得出答案 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 1000010
    int n,link[maxn],num,head[maxn*2];
    bool vis[maxn];
    struct node{
        int to,pre;
    }e[maxn*2];
    void Insert(int from,int to){
        e[++num].to=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    bool dfs(int x){
        for(int i=head[x];i;i=e[i].pre){
            int to=e[i].to;
            if(!vis[to]){
                vis[to]=1;
                if(!link[to]||dfs(link[to])){
                    link[to]=x;return 1;
                }
            }
        }
        return 0;
    }
    int main(){
        scanf("%d",&n);
        int x,y;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            if(x<=n)Insert(x,i);
            if(y<=n)Insert(y,i);
        }
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof(vis));
            if(!dfs(i)){
                printf("%d",i-1);
                return 0;
            }
        }
        printf("%d",n);
        return 0;
    }
    二分图匹配
    /*
        并查集的做法一直没明白过来,手模了几个数据,有那么一瞬间觉得好像蛮有道理的,后来运行了一组数据,输出结果和手膜的不一样,我感觉这个算法肯定存在漏洞,还是写二分图去吧。 
    */
    /*
        错误数据
        Input
        3
        1 5
        2 4
        3 6
        Output 
        3 
    */
    #include<iostream>
    #include<cstdio>
    #define maxn 1000010
    using namespace std;
    int n,fa[maxn],sz[maxn],ans;
    bool vis[maxn];
    int find(int x){
        if(x==fa[x])return x;
        else return fa[x]=find(fa[x]);
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d",&n);int x,y;
        for(int i=1;i<=n+1;i++)fa[i]=i;
        for(int i=1;i<=n+1;i++)sz[i]=1;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            int f1=find(x),f2=find(y);
            if(f1==f2)vis[f1]=1;
            else{
                vis[f1]=vis[f1]|vis[f2];vis[f2]=0;
                sz[f1]+=sz[f2];sz[f2]=0;
                fa[f2]=f1;
            }
        }
        for(int i=1;i<=n+1;i++){
            int x=find(i);
            if(!vis[x]){
                if(sz[x]==1){ans=i-1;break;}
                else sz[x]--;
            }
        }
        printf("%d",ans);
    }
    并查集
  • 相关阅读:
    1052 Linked List Sorting (25 分)
    1051 Pop Sequence (25 分)
    1050 String Subtraction (20 分)
    1049 Counting Ones (30 分)
    1048 Find Coins (25 分)
    1047 Student List for Course (25 分)
    1046 Shortest Distance (20 分)
    1045 Favorite Color Stripe (30 分)
    1044 Shopping in Mars (25 分)
    1055 The World's Richest (25 分)
  • 原文地址:https://www.cnblogs.com/thmyl/p/7610089.html
Copyright © 2020-2023  润新知