UVA 1345 Jamie's Contact Groups

题意:

  一些人,和他们可能加入的组号。问每个组,最小的最大人数是多少

分析:

  二分的是最大流的容量。设置一个超级源点,连向所有的人,容量为1。设置一个超级汇点,使所有的组连向超级汇点,二分的就是这里的容量(0~n)。然后根据题目给出的人和组的关系连接人和组,容量为1。二分时,若当前状态求出的最大流等于人数,则下界等于mid,若不等于,则上界等于mid。二分出的容量,就是组中的最小的最大人数。

输入:

3 2

John 0 1

Rose 1

Mary 1

5 4

ACM 1 2 3

ICPC 0 1

Asian 0 2 3

Regional 1 2

ShangHai 0 2

0 0 

输出:

2

2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <sstream>
using namespace std;
const int maxn=3010;
const int inf=1e9;
int n,m;
structEdge
{
    int u,v;
    int flow,cap;
    Edge(int uu,int cc,int fl,int ca):u(uu),v(cc),flow(fl),cap(ca)
    {

    }
};
vector<Edge>edge;
structISAP
{
    vector<int>G[maxn];
    vector<Edge>edge;
    int s,t;
    int d[maxn];
    int cur[maxn];
    int p[maxn];
    int num[maxn];
    int flow;
    void init()
    {
        for(int i=0;i<=n+m+1;i++)
            G[i].clear();
        s=0;
        t=n+m+1;
    }
    bool bfs()
    {
        memset(d,-1,sizeof(d));
        queue<int>q;
        q.push(t);
        d[t]=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0;i<G[u].size();i++)
            {
                Edge& e=edge[G[u][i]];
                if(e.cap==0&&d[e.v]==-1)
                {
                    d[e.v]=d[u]+1;
					q.push(e.v);
                }
            }
        }
        return d[s]!=-1;
    }
    int Augment()
    {
        int x=t,a=inf;
        while(x!=s)
        {
            Edge& e=edge[p[x]];
            a=min(a,e.cap-e.flow);
            x=edge[p[x]].u;
        }
        x=t;
        while(x!=s)
        {
            edge[p[x]].flow+=a;
            edge[p[x]^1].flow-=a;
            x=edge[p[x]].u;
        }
        return a;
    }
    int maxflow(int s,int t)
    {
        this->s=s;
        this->t=t;
        flow=0;
        bfs();
        for(int i=0;i<=n+m+1;i++)
            num[d[i]]++;
        int x=s;
        memset(cur,0,sizeof(cur));
        while(d[s]<n+m+2)
        {
            if(x==t)
            {
                flow+=Augment();
                x=s;
            }
            bool ok=false;
            for(int i=cur[x];i<G[x].size();i++)
            {
                Edge& e=edge[G[x][i]];
                if(e.cap>e.flow&&d[x]==d[e.v]+1)
                {
                    ok=true;
                    p[e.v]=G[x][i];
                    cur[x]=i;
                    x=e.v;
                    break;
                }
            }
            if(!ok)
            {
                int k=n+m+1;
                for(int i=0;i<G[x].size();i++)
                {
                    Edge& e=edge[G[x][i]];
                    if(e.cap>e.flow)
                        k=min(k,d[e.v]);
                }
                if(--num[d[x]]==0)
                    break;
                num[d[x]=k+1]++;
                cur[x]=0;
                if(x!=s)
                    x=edge[p[x]].u;
            }
        }
        return flow;
    }
}solver;
char buffer[11000];
void add(int s,int t,int cap)
{
    edge.push_back(Edge(s,t,0,cap));
    edge.push_back(Edge(t,s,0,0));
    int x=edge.size();
    solver.G[s].push_back(x-2);
    solver.G[t].push_back(x-1);
}
void input()
{
    solver.init();
    int x;
    edge.clear();
    char ch[100];
    for (int i = 1 ; i <= n ; ++i)
    {
		add(0,i,1);
		scanf("%*s");
		gets(buffer);
		char * p = strtok(buffer, " ");
		while (p) {
			sscanf(p,"%d",&x);
			add(i,x+1+n,1);
			p = strtok(NULL," ");
		}
	}
    int sz=edge.size();
    for(int i=n+1;i<=n+m;i++)
    {
        sz+=2;
        solver.G[i].push_back(sz-2);
        solver.G[n+m+1].push_back(sz-1);
    }
}
void build(int up)
{
    solver.edge=edge;
    for(int i=n+1;i<=n+m;i++)
    {
        solver.edge.push_back(Edge(i,n+m+1,0,up));
		solver.edge.push_back(Edge(n+m+1,i,0,0));
    }
}
void solve()
{
    int left=1,right=n;
    int mid=(left+right)>>1;
    int ans=n;
    while(left<=right)
    {
        build(mid);
        if (solver.maxflow(0,n+m+1)==n)
        {
			right = mid-1;
			ans = min(ans,mid);
		}
		else
        {
			left = mid+1;
		}
		mid = (left+right)>>1;
    }
    printf("%d\n",ans);
}
int main()
{
	while(scanf("%d%d",&n,&m)==2,n+m)
	{
		input();
		solve();
	}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <sstream>
using namespace std;
const int maxn=3010;
const int inf=1e9;
int n,m;
structEdge
{
    int u,v;
    int flow,cap;
    Edge(int uu,int cc,int fl,int ca):u(uu),v(cc),flow(fl),cap(ca)
    {

    }
};
vector<Edge>edge;
structISAP
{
    vector<int>G[maxn];
    vector<Edge>edge;
    int s,t;
    int d[maxn];
    int cur[maxn];
    int p[maxn];
    int num[maxn];
    int flow;
    void init()
    {
        for(int i=0;i<=n+m+1;i++)
            G[i].clear();
        s=0;
        t=n+m+1;
    }
    bool bfs()
    {
        memset(d,-1,sizeof(d));
        queue<int>q;
        q.push(t);
        d[t]=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0;i<G[u].size();i++)
            {
                Edge& e=edge[G[u][i]];
                if(e.cap==0&&d[e.v]==-1)
                {
                    d[e.v]=d[u]+1;
					q.push(e.v);
                }
            }
        }
        return d[s]!=-1;
    }
    int Augment()
    {
        int x=t,a=inf;
        while(x!=s)
        {
            Edge& e=edge[p[x]];
            a=min(a,e.cap-e.flow);
            x=edge[p[x]].u;
        }
        x=t;
        while(x!=s)
        {
            edge[p[x]].flow+=a;
            edge[p[x]^1].flow-=a;
            x=edge[p[x]].u;
        }
        return a;
    }
    int maxflow(int s,int t)
    {
        this->s=s;
        this->t=t;
        flow=0;
        bfs();
        for(int i=0;i<=n+m+1;i++)
            num[d[i]]++;
        int x=s;
        memset(cur,0,sizeof(cur));
        while(d[s]<n+m+2)
        {
            if(x==t)
            {
                flow+=Augment();
                x=s;
            }
            bool ok=false;
            for(int i=cur[x];i<G[x].size();i++)
            {
                Edge& e=edge[G[x][i]];
                if(e.cap>e.flow&&d[x]==d[e.v]+1)
                {
                    ok=true;
                    p[e.v]=G[x][i];
                    cur[x]=i;
                    x=e.v;
                    break;
                }
            }
            if(!ok)
            {
                int k=n+m+1;
                for(int i=0;i<G[x].size();i++)
                {
                    Edge& e=edge[G[x][i]];
                    if(e.cap>e.flow)
                        k=min(k,d[e.v]);
                }
                if(--num[d[x]]==0)
                    break;
                num[d[x]=k+1]++;
                cur[x]=0;
                if(x!=s)
                    x=edge[p[x]].u;
            }
        }
        return flow;
    }
}solver;
char buffer[11000];
void add(int s,int t,int cap)
{
    edge.push_back(Edge(s,t,0,cap));
    edge.push_back(Edge(t,s,0,0));
    int x=edge.size();
    solver.G[s].push_back(x-2);
    solver.G[t].push_back(x-1);
}
void input()
{
    solver.init();
    int x;
    edge.clear();
    char ch[100];
    for (int i = 1 ; i <= n ; ++i)
    {
		add(0,i,1);
		scanf("%*s");
		gets(buffer);
		char * p = strtok(buffer, " ");
		while (p) {
			sscanf(p,"%d",&x);
			add(i,x+1+n,1);
			p = strtok(NULL," ");
		}
	}
    int sz=edge.size();
    for(int i=n+1;i<=n+m;i++)
    {
        sz+=2;
        solver.G[i].push_back(sz-2);
        solver.G[n+m+1].push_back(sz-1);
    }
}
void build(int up)
{
    solver.edge=edge;
    for(int i=n+1;i<=n+m;i++)
    {
        solver.edge.push_back(Edge(i,n+m+1,0,up));
		solver.edge.push_back(Edge(n+m+1,i,0,0));
    }
}
void solve()
{
    int left=1,right=n;
    int mid=(left+right)>>1;
    int ans=n;
    while(left<=right)
    {
        build(mid);
        if (solver.maxflow(0,n+m+1)==n)
        {
			right = mid-1;
			ans = min(ans,mid);
		}
		else
        {
			left = mid+1;
		}
		mid = (left+right)>>1;
    }
    printf("%d\n",ans);
}
int main()
{
	while(scanf("%d%d",&n,&m)==2,n+m)
	{
		input();
		solve();
	}
}
posted @ 2016-08-11 17:08  幻世沉溺  阅读(147)  评论(0编辑  收藏  举报