zoukankan      html  css  js  c++  java
  • 洛谷P5030 长脖子鹿放置(二分图+最大独立集)

    题目链接:https://www.luogu.com.cn/problem/P5030

    提示:二分图最大独立集=点数-最小点覆盖(最大匹配)

    题解:这个题其实想想的话可以知道,应该把一些互吃边连在一起建边,把n*n的图划分成一个个的点并标号,有些是陷阱点,所以不用和他进行建边。这样我们能看出来是一个求最大独立集的问题(即二分图相邻2点不连的话最大可包括几个点)。想到了就还挺容易的吧。关于建边其实可以有优化(没有优化也可以过但是浪费时间)。因为我们看到其实其实行是奇数的话,其互吃点必在偶数行,所以可以进一步简化到奇偶边建边(可以省去一半的建边)。而且对于同排多点建边其实你用一个add就可以了,没必要2个add最后除2,亲测有效。

    AC100分代码(记得一开始的:不保证禁止放置的格子互不相同。需要去重):

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[1000005];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m,k,cnt,used[200*200+5],match[200*200+5];
    int find(int x){
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!used[v]){
                used[v]=true;
                if(!match[v]||find(match[v])){
                    match[v]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int a[305][305];
    int dx[8]={-3,3,-3,3,-1,1,-1,1};
    int dy[8]={1,1,-1,-1,3,3,-3,-3};
    int f(int x,int y){
        return (x-1)*m+y;
    }
    int main(){
        cin>>n>>m>>k;mem(head,-1);
        int cnt=0;
        rep(i,1,k){
            int x,y;cin>>x>>y;
            if(!a[x][y]){
                a[x][y]=1;++cnt;
            }
        }    
        rep(i,1,n){
            rep(j,1,m){
                if(!a[i][j]&&i%2==0){
                    rep(k,0,7){
                        int x=i+dx[k],y=j+dy[k];
                        if(x>0&&x<=n&&y>0&&y<=m&&!a[x][y]){
                            add(f(i,j),f(x,y));
                        }
                    }
                }
            }
        }
        int ans=0;
        rep(i,1,f(n,m)){
            mem(used,0);
            if(find(i)) ans+=1;
        }
        cout<<n*m-ans-cnt<<endl;    
    }
    /*
    8 7 5
    1 1
    5 4
    2 3
    4 7
    8 3
    */
    View Code
  • 相关阅读:
    Effective JavaScript Item 40 避免继承标准类型
    基于express+redis高速实现实时在线用户数统计
    HDOJ 4009 Transfer water 最小树形图
    iOS Sprite Kit教程之xcode安装以及苹果帐号绑定
    Swift2.0语言教程之类的嵌套与可选链接
    Swift2.0语言教程之下标脚本
    Swift2.0语言教程之类的方法
    Swift2.0语言教程之类的属性
    Swift2.0语言教程之闭包
    Swift2.0语言教程之函数嵌套调用形式
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13355138.html
Copyright © 2011-2022 走看看