zoukankan      html  css  js  c++  java
  • bzoj1305: [CQOI2009]dance跳舞

    网络流拆点建模。

    注意二分查找的边界

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 500 + 10;
    const int maxm = 40000 + 10;
    const int INF = 0x3f3f3f3f;
    
    int g[maxn],v[maxm],next[maxm],f[maxm],eid;
    int S,T,vid;
    int id[maxn][2][2];
    char m[60][60];
    int n,k;
    int dist[maxn],gap[maxn];
    
    void addedge(int a,int b,int c) {
        v[eid]=b; f[eid]=c; next[eid]=g[a]; g[a]=eid++;
        v[eid]=a; f[eid]=0; next[eid]=g[b]; g[b]=eid++;
    }
    
    void build(int x) {
        memset(g,-1,sizeof(g)); eid=0;
        for(int i=1;i<=n;i++) {
            addedge(S,id[i][0][0],x);
            addedge(id[i][0][0],id[i][0][1],k);
            addedge(id[i][1][1],id[i][1][0],k);
            addedge(id[i][1][0],T,x);    
        }
        
        for(int i=1;i<=n;i++) 
        for(int j=1;j<=n;j++) {
            if(m[i][j]=='Y') addedge(id[i][0][0],id[j][1][0],1);
            else addedge(id[i][0][1],id[j][1][1],1);
        }
    }
    
    int ISAP(int u,int flow) {
        if(u==T) return flow;
        
        int aug,cur=0,mindist=vid;
        for(int i=g[u];~i;i=next[i]) 
            if(f[i]&& dist[v[i]]+1==dist[u]) {
                aug=ISAP(v[i],min(flow-cur,f[i]));
                f[i]-=aug;
                f[i^1]+=aug;
                cur+=aug;
                if(cur==flow || dist[S]>=vid) {
                    return cur;
                }
            }
    
        if(cur==0) {
            if(!--gap[dist[u]]) {
                dist[S]=vid;
                return cur;
            }
            for(int i=g[u];~i;i=next[i]) if(f[i])
                mindist=min(mindist,dist[v[i]]);
            ++gap[dist[u]=mindist+1];
        }
        
        return cur;
    }
    
    int max_flow() {
        memset(gap,0,sizeof(gap));
        memset(dist,0,sizeof(dist));
        gap[0]=vid;
        
        int res=0;
        while(dist[S]<vid) res+=ISAP(S,INF);
        return res;
    }
    
    
    bool check(int x) {
        build(x);
        return (max_flow()==x*n);
    }
    
    int main() {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%s",m[i]+1);
            for(int x=0;x<=1;x++)
            for(int y=0;y<=1;y++)
                id[i][x][y]=++vid;    
        }
        S=++vid; T=++vid;
        
        int l=0,r=n,mid;
        while(l+1<r) {
            mid=(l+r)>>1;
            if(check(mid)) l=mid;
            else r=mid-1;            
        }
        printf("%d
    ",check(r)?r:l);
        return 0;
    }
  • 相关阅读:
    datagrid
    SQL语句
    JavaScript事件
    DOM和BOM
    JavaScript基础知识
    css
    网络编程常识
    集合框架
    多线程常识
    面向对象常识
  • 原文地址:https://www.cnblogs.com/invoid/p/5497315.html
Copyright © 2011-2022 走看看