zoukankan      html  css  js  c++  java
  • P1640 [SCOI2010]连续攻击游戏

    以前做这题的时候没啥思路。该多练练找性质的题了。尤其这个性质还这么显然。

    考虑环的情况:如果把每一个装备的两个性质连边,任何一个环上的所有点都能取到。

    应该不难理解吧。进一步可以发现,从这个环往外扩展,整个联通块都能被取到。

    所以只剩下树的情况了。我们惊喜地发现边变少了,可以用二分图做了。

    其实可以继续找性质,优化到(O(n)),懒得想了。

    记得数组要开2倍 别问为什么

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    #define forg(i,x) for(int i=first[x];i;i=nxt[i])
    #define uu unsigned
    #define fi first
    #define se second
    #define od(x) ((x)&1)
    #define ev(x) (od(x)^1)
    #define mi2(x) (1<<(x))
    #define scanf a1234=scanf
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
    #define rint register int
    int a1234;
    char buf[1<<18],*bufs=buf,*buft=buf;
    inline int gc(){
        return bufs==buft&&(buft=(bufs=buf)+fread(buf,1,1<<18,stdin)),bufs==buft?-1:*bufs++;
    }
    inline void xxx(){for(;;);}
    
    const int mxn=1e6+3,mxm=1e4+3;
    int n,m;pii a[mxn];
    int to[mxn<<1],nxt[mxn<<1],first[mxn],tot=1,dep[mxn];
    bool vis[mxn],cd[mxn];
    inline void gadd(int x,int y){to[++tot]=y,nxt[tot]=first[x],first[x]=tot;}
    inline void dfs1(int x){
        if(cd[x])return;cd[x]=1;
        forg(i,x)dfs1(to[i]);
    }
    
    inline void dfs(int x,int e){
        vis[x]=1;
        forg(i,x)if(i!=(e^1)){
            if(!vis[to[i]]){dep[to[i]]=dep[x]+1,dfs(to[i],i);}
            else dfs1(x);
        }
    }
    struct eft{
        int mch[mxm],to[mxm<<1],nxt[mxm<<1],first[mxm],tot,nn,vis[mxm];
        inline void gadd(int x,int y){to[++tot]=y,nxt[tot]=first[x],first[x]=tot;}
        inline void add(int x){++nn;gadd(a[x].fi,nn),gadd(a[x].se,nn);}
        inline bool hung(rint x,rint xh){
            if(vis[x]==xh)return 0;vis[x]=xh;
            forg(i,x){
                if(!mch[to[i]]||hung(mch[to[i]],xh))return mch[to[i]]=x,1;
            }
            return 0;
        }
    //    inline bool work(rint x){return hung(x);}
    }gg;
    
    int main(){fre(game);
        scanf("%d",&n);for(int i=1,u,v;i<=n;++i)scanf("%d%d",&u,&v),gadd(u,v),gadd(v,u),a[i]=pii(u,v),m=max(m,max(u,v));
        
        for(int i=1;i<=m;++i)if(!vis[i])dfs(i,0);
        for(int i=1;i<=n;++i)if(!cd[a[i].fi])gg.add(i);
        int ans=0;
        for(int i=1;i<=m;++i)if(cd[i]||gg.hung(i,i))++ans;else break;
        printf("%d
    ",ans);
        return 0;
    }
    
    

    upd 突然发现郭巨佬做法和我一样 不过他是直接秒掉 隔空orz

  • 相关阅读:
    【Hadoop】HDFS笔记(一):Hadoop的RPC机制
    英文分句
    破解google翻译API全过程
    最大匹配算法 (Maximum Matching)
    【Html 学习笔记】第八节——表单实践
    【Html 学习笔记】第七节——表单
    【Html 学习笔记】第六节——列表
    Linux下第一次Node尝试
    【Html 学习笔记】第五节——表格
    C++并发低级接口:std::thread和std::promise
  • 原文地址:https://www.cnblogs.com/happyguy/p/13844585.html
Copyright © 2011-2022 走看看