• BZOJ1854: [Scoi2010]游戏 二分图


    很早之前写的题了,发现没有更博,想了想,更一发出来。

    Orz ljss

    这是冬令营上的例题...之后,我推出来了一种时间复杂度没有问题,空间复杂度没有问题的方法,额(⊙o⊙)…和给出的正解不同,但是能AC

    分析:

    正解是什么我忘了,我还是讲一下我自己的方法吧...

    首先,这是一个并查集的题...但是,我没有用并查集...之后呢,我当时并不会二分图,也不会匈牙利...之后,我根据臆测...莫名其妙的想到了用二分图+匈牙利算法的方法解决这道题...(这也可以?!)

    我们可以这样考虑一下,每个武器有两个属性,那么我们可以连两条边,属性和对应的武器号,顺便,开一个桶处理出每一个属性有多少把武器。

    之后呢,枚举答案,对,枚举答案!

    枚举答案从1到最大值,判断一下桶中的个数是否为0,如果为0,输出i-1,并且退出程序

    如果桶中个数为1,那么说明,如果想要到达这个答案,我们必须使用这把武器的这个属性,那么,我们在对应武器的另一个属性的桶中减去这把武器,即:num[a[i^1]]--;

    并且,将这把武器打上标记,下次使用的时候,不能继续使用。

    在a[i^1]<a[i]的前提下:

    如果num[a[i^1]]减成0,那么答案为i-1,并且退出程序。

    如果num[a[i^1]]大于1,那么继续枚举答案。

    如果num[a[i^1]]恰好等于1,那么我们递归的继续处理a[i^1]这个属性,处理方法同上。

    (手动模拟匈牙利算法,捂脸!!!鬼知道我当时怎么想出来的!!!)

    时间复杂度:(可过)

    附上代码:

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    #define N 1000005
    #define M 10005
    int n;
    int a[N<<1],num[M],u;
    bool vis[N<<1];
    struct node
    {
        int to,next;
    }e[N<<1];
    int head[M],cnt;
    void add(int x,int y)
    {
        e[cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt++;
        return ;
    }
    bool work(int x)
    {
        if(num[x]==0&&u>=x)return 0;
        if(num[x]==1&&u>=x)
        {
            for(int i=head[x];i!=-1;i=e[i].next)
            {
                int to1=e[i].to;
                if(!vis[to1])
                {
                    num[a[to1^1]]--;
                    vis[to1]=vis[to1^1]=1;
                    if(!work(a[to1^1]))
                    {
                        return 0;
                    }else
                    {
                        return 1;
                    }
                }
            }
        }
        return 1;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        scanf("%d",&n);
        for(int i=0;i<(n<<1);i++)
        {
            scanf("%d",&a[i]);
            num[a[i]]++;
            add(a[i],i);
        }
        int i;
        for(i=1;i<M;i++)
        {
            if(num[i]==0)break;
            if(num[i]==1)
            {
                u=i;
                if(!work(i))
                {
                    break;
                }
            }
        }
        printf("%d
    ",i-1);
        return 0;
    }
    

      

  • 相关阅读:
    hdu4651(广义五边形数 & 分割函数1)
    Java基础面试题1
    Java8新特性--Lambda表达式
    Java中list在循环中删除元素的坑
    Java多线程面试题整理
    Java并发包--ConcurrentHashMap原理解析
    HashMap原理解析
    Java原子类--AtomicLongFieldUpdater
    Java原子类--AtomicReference
    Java原子类--AtomicLongArray
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9005270.html
Copyright © 2020-2023  润新知