zoukankan      html  css  js  c++  java
  • [BZOJ] 1191: [HNOI2006]超级英雄Hero

    一看:裸二分图最大匹配/最大流么,码码码

    交,WA..

    仔细读题,是这样的,一旦有一个题答不出游戏就结束了,看起来需要动态加边的最大流?

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define Ri(x) ((x)+m)
    using namespace std;
    
    inline int rd() {
        int ret=0,f=1;
        char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=2048;
    const int INF=1<<29;
    
    struct Edge {
        int next,to,w;
    } e[MAXN<<2];
    int ecnt=1,head[MAXN];
    inline void add(int x,int y,int w) {
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        e[ecnt].w = w;
        head[x] = ecnt;
    }
    
    int n,m;
    int S,T;
    bool visr[MAXN];
    
    int dep[MAXN];
    queue<int> Q;
    bool bfs() {
        memset(dep,0,sizeof(dep));
        Q.push(S);
        dep[S]=1;
        while(!Q.empty()) {
            int top=Q.front();
            Q.pop();
            for(int i=head[top]; i; i=e[i].next) {
                int v=e[i].to;
                if(!e[i].w||dep[v]) continue;
                dep[v]=dep[top]+1;
                Q.push(v);
            }
        }
        return dep[T];
    }
    
    int cur[MAXN];
    int dfs(int x,int flow) {
        if(x==T) return flow;
        int used=0,tmp;
        for(int i=cur[x]; i; i=e[i].next) {
            int v=e[i].to;
            if(dep[v]!=dep[x]+1) continue;
            tmp=dfs(v,min(e[i].w,flow-used));
            e[i].w-=tmp;
            e[i^1].w+=tmp;
            used+=tmp;
            if(e[i].w) cur[x]=i;
            if(used==flow) return flow;
        }
        if(!used) dep[x]=0;
        return used;
    }
    
    int mxflow;
    void dinic() {
        while(bfs()) {
            memcpy(cur,head,sizeof(head));
            mxflow+=dfs(S,INF);
        }
    }
    
    bool vis[MAXN];
    
    int main() {
        n=rd();
        m=rd();
        S=n+m+1;
        T=n+m+2;
        int x,y;
    
        for(int i=1; i<=m; i++) {
            add(S,i,1),add(i,S,0);
            x=rd();y=rd();x++;y++;
            add(i,Ri(x),1);add(Ri(x),i,0);
            if(!vis[x]) add(Ri(x),T,1),add(T,Ri(x),0);
            vis[x]=1;
            if(x!=y) {
                add(i,Ri(y),1);add(Ri(y),i,0);
                if(!vis[y]) add(Ri(y),T,1),add(T,Ri(y),0);
                vis[y]=1;
            }
            dinic();
            if(mxflow<i) return cout<<mxflow,0;
        }
        cout<<mxflow;
        return 0;
    }

    但是有这样一个事情,如果能答x道,一定能答y (y<x)道(显然啊)

    因此可以二分一下!dinic的优秀复杂度,不慢的

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define Ri(x) ((x)+m)
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=2048;
    const int INF=1<<29;
    
    struct Edge{
        int next,to,w;
    }e[MAXN<<2];
    int ecnt=1,head[MAXN];
    inline void add(int x,int y,int w){
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        e[ecnt].w = w;
        head[x] = ecnt;
    }
    
    int n,m;
    int S,T;
    
    int dep[MAXN];
    queue<int> Q;
    bool bfs(){
        memset(dep,0,sizeof(dep));
        Q.push(S);dep[S]=1;
        while(!Q.empty()){
            int top=Q.front();Q.pop();
            for(int i=head[top];i;i=e[i].next){
                int v=e[i].to;
                if(!e[i].w||dep[v]) continue;
                dep[v]=dep[top]+1;
                Q.push(v);
            }
        }
        return dep[T];
    }
    
    int cur[MAXN];
    int dfs(int x,int flow){
        if(x==T) return flow;
        int used=0,tmp;
        for(int i=cur[x];i;i=e[i].next){
            int v=e[i].to;
            if(dep[v]!=dep[x]+1) continue;
            tmp=dfs(v,min(e[i].w,flow-used));
            e[i].w-=tmp;e[i^1].w+=tmp;
            used+=tmp;
            if(e[i].w) cur[x]=i;
            if(used==flow) return flow;
        }
        if(!used) dep[x]=0;
        return used;
    }
    
    int mxflow;
    void dinic(){
        while(bfs()){
            memcpy(cur,head,sizeof(head));
            mxflow+=dfs(S,INF);
        }
    }
    
    int savx[MAXN],savy[MAXN];
    
    bool solve(int mid){
        ecnt=1;
        memset(head,0,sizeof(head));
        mxflow=0;
        int x,y;
        for(int i=1;i<=mid;i++){
            x=savx[i];y=savy[i];
            add(i,Ri(x),1);add(Ri(x),i,0);
            if(x==y) continue;
            add(i,Ri(y),1),add(Ri(y),i,0);
        }
        for(int i=1;i<=m;i++) add(S,i,1),add(i,S,0);
        for(int i=1;i<=n;i++){
            add(Ri(i),T,1);add(T,Ri(i),0);
        }
        dinic();
        return mxflow==mid;
    }
    
    int main(){
        n=rd();m=rd();
        S=n+m+1;T=n+m+2;
        int x,y;
        for(int i=1;i<=m;i++){
            savx[i]=rd()+1;savy[i]=rd()+1;
            add(i,Ri(x),1);add(Ri(x),i,0);
        }
        int l=0,r=m,mid,ans;
        while(l<=r){
            mid=(l+r)>>1;
            if(solve(mid)) l=mid+1,ans=mid;
            else r=mid-1;
        }
        cout<<ans;
        return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9401741.html

  • 相关阅读:
    一个方法只做一件事
    日常-生活-学习-经验分享
    Python 用下划线作为变量前缀和后缀指定特殊变量
    浏览器渲染的基本原理
    七个对我最好的职业建议
    web性能优化
    Javascript 设计模式
    数据结构与算法 Javascript描述
    mysql计算连续天数,mysql连续登录天数,连续天数统计
    Oracle计算连续天数,计算连续时间,Oracle连续天数统计
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9401741.html
Copyright © 2011-2022 走看看