现在的位置: 首页 > 综合 > 正文

poj 2289 二分枚举+最大流

2013年12月03日 ⁄ 综合 ⁄ 共 1417字 ⁄ 字号 评论关闭

传送门

题意:有很多联系方式要分组,每个联系方式可以分到若干个组去,问最多的那组最少会有多少联系方式。

思路:稍想了一下,就想到了二分枚举答案,然后看最大流是否等于n,然后取最小的输出。一开始TLE,后来改成手写队列,然后wa,后来发现打错一个字母,然后过了。

瞎想:坚持了这么久的EK算法,我想迟早逃脱不了TLE的命运,是不是该学习新的算法了呢?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int m,n,s,t,fst[2000],next[600000],node[600000],c[600000];
int en,f[600000],h[505],hnum,pre[2000],lu[2000];
bool vis[2000];
char str[30];
void init()
{
    en=0;
    hnum=0;
    memset(fst,-1,sizeof(fst));
}
void add(int u,int v,int cc)
{
    next[en]=fst[u];
    fst[u]=en;
    node[en]=v;
    c[en]=cc;
    en++;
}
void change(int cc)
{
    for(int i=0;i<hnum;i++)
    {
        c[h[i]]=cc;
    }
}
bool bfs()
{
    memset(vis,0,sizeof(vis));
    int q[2000];
    int front=0,end=0;
    q[end++]=s;
    vis[s]=1;
    while(front<end)
    {
        int u=q[front++];
        for(int i=fst[u];i!=-1;i=next[i])
        {
            int v=node[i];
            if(!vis[v]&&c[i]>f[i])
            {
                pre[v]=u;
                lu[v]=i;
                vis[v]=1;
                if(v==t)return true;
                q[end++]=v;
            }
        }
    }
    return false;
}
int ek()
{
    int flow=0;
    memset(f,0,sizeof(f));
    while(bfs())
    {
        for(int i=t;i!=s;i=pre[i])
        {
            int v=lu[i];
            f[v]+=1;
            f[v^1]-=1;
        }
        flow+=1;
    }
    return flow;
}
void solve()
{
    int ans=n;
    int left=1,right=n,mid;
    while(left<=right)
    {
        mid=(left+right)/2;
        change(mid);
        if(ek()==n)
        {
            ans=min(mid,ans);
            right=mid-1;
        }
        else
        {
            left=mid+1;
        }
    }
    cout<<ans<<endl;
}
int main()
{
    int u;
    while(scanf("%d%d",&n,&m))
    {
        if(m==0&&n==0)break;
        init();
        s=0;
        t=m+n+2;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            while(getchar()!='\n')
            {
                scanf("%d",&u);
                add(i,u+n+1,1);
                add(u+n+1,i,0);
            }
            add(0,i,1);
            add(i,0,0);
        }
        for(int i=0;i<m;i++)
        {
            h[hnum++]=en;
            add(n+i+1,t,1);
            add(t,n+i+1,0);
        }
        solve();
    }
    return 0;
}

抱歉!评论已关闭.