• 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

  • 相关阅读:
    HDU 3572 Task Schedule(拆点+最大流dinic)
    POJ 1236 Network of Schools(Tarjan缩点)
    HDU 3605 Escape(状压+最大流)
    HDU 1166 敌兵布阵(分块)
    Leetcode 223 Rectangle Area
    Leetcode 219 Contains Duplicate II STL
    Leetcode 36 Valid Sudoku
    Leetcode 88 Merge Sorted Array STL
    Leetcode 160 Intersection of Two Linked Lists 单向链表
    Leetcode 111 Minimum Depth of Binary Tree 二叉树
  • 原文地址:https://www.cnblogs.com/happyguy/p/13844585.html
Copyright © 2020-2023  润新知