hdu 3081&hdu 3277 (最大流)

hdu 3081题意:n个女孩,n个男孩,每个女孩有自己喜欢的男孩,她也会喜欢自己朋友喜欢的男孩,朋友间的关系是可以传递的。每个女孩每轮游戏要找一个喜欢的男孩过家家。问游戏最多能玩多少轮。

hdu 3277:跟3081题目意思大概一样,就是加了一个每个女孩可以选k个自己不喜欢的男孩。

hdu 3081:思路:图是二分图,如果把每个女孩跟喜欢的男孩连边,建设能玩D轮游戏,就是该图的最大流是D*n了,所以加上源点汇点,再二分找出最大的游戏论数。

hdu 3277:在一题上把女孩拆成两个点,拆出来的点连接不喜欢的男孩,在二分建图时不能太复杂,不然得TLE。





hdu 3081:

#include<stdio.h>
#include<string.h>
const int N=300;
const int inf=0x3fffffff;
int head[N],num,gap[N],dis[N],first[N],tot,f[N],start,end,ans,n;
bool map[110][110];
struct edge
{
    int st,ed,flow,next;
}e[N*10000];
struct node
{
    int ed,next;
}E[N*N];
int find(int a)
{
    if(a!=f[a])
        f[a]=find(f[a]);
    return f[a];
}
void addedge(int x,int y,int w)
{
    e[num].ed=y;e[num].flow=w;e[num].next=head[x];head[x]=num++;
    e[num].ed=x;e[num].flow=0;e[num].next=head[y];head[y]=num++;
}
void Addedge(int x,int y)
{
    E[tot].ed=y;E[tot].next=first[x];first[x]=tot++;
}
int dfs(int u,int minflow)  
{  
	if(u==end)return minflow;  
	int i,v,f,min_dis=ans-1,flow=0;  
	for(i=head[u];i!=-1;i=e[i].next)  
	{  
		v=e[i].ed;  
		if(e[i].flow<=0)continue;  
		if(dis[v]+1==dis[u])  
		{  
			f=dfs(v,e[i].flow>minflow-flow?minflow-flow:e[i].flow);  
			e[i].flow-=f;  
			e[i^1].flow+=f;  
			flow+=f;  
			if(flow==minflow)break;  
			if(dis[start]>=ans)return flow;  
		}  
		min_dis=min_dis>dis[v]?dis[v]:min_dis;  
	}  
	if(flow==0)  
	{  
		if(--gap[dis[u]]==0)  
			dis[start]=ans;  
		dis[u]=min_dis+1;  
		gap[dis[u]]++;  
	}  
	return flow;  
}
int isap()
{
    int maxflow=0;
    memset(gap,0,sizeof(gap));
    memset(dis,0,sizeof(dis));
    gap[0]=ans;
    while(dis[start]<ans)
        maxflow+=dfs(start,inf);
    return maxflow;
}
bool judge(int D)
{
    memset(head,-1,sizeof(head));
    num=0;
    int i,j;
    for(i=1;i<=n;i++)
	{
		addedge(start,i,D);
		addedge(i+n,end,D);
		for(j=1;j<=n;j++)
		{
			if(map[i][j])addedge(i,j+n,1);
		}		
	}
    if(isap()==n*D)
        return true;
    return false;
}
int main()
{
    int i,j,k,m,F,t,x,y,flag;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&F);
        tot=0;start=0;end=n+n+1;ans=end+1;
        memset(first,-1,sizeof(first));
		memset(map,false,sizeof(map));
        for(i=1;i<=n;i++)
            f[i]=i;
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            Addedge(x,y);
			map[x][y]=true;
        }
        while(F--)
        {
            scanf("%d%d",&x,&y);
            if(find(x)!=find(y))
				f[find(x)]=find(y);
        }
		for(i=1;i<=n;i++)
        {
            for(j=i+1;j<=n;j++)
            {
                if(find(i)!=find(j))continue;
                for(k=first[i];k!=-1;k=E[k].next)
                    map[j][E[k].ed]=true;
                for(k=first[j];k!=-1;k=E[k].next)
                    map[i][E[k].ed]=true;                    
            }
        }
        int L=0,R=n,mid;
        flag=0;
        while(L<=R)
        {
            mid=(L+R)>>1;
            if(judge(mid))
            {
                flag=mid;
                L=mid+1;
            }
            else R=mid-1;
        }
        printf("%d\n",flag);
    }
    return 0;
}

hdu 3277:



#include<stdio.h>
#include<string.h>
const int N=1000;
const int inf=0x3fffffff;
int head[N],num,gap[N],dis[N],first[N],tot,f[N],start,end,ans,n,K;
bool map[300][300];
struct edge
{
    int st,ed,flow,next;
}e[N*1000];
struct node
{
    int ed,next;
}E[N*N];
int find(int a)
{
    if(a!=f[a])
        f[a]=find(f[a]);
    return f[a];
}
void addedge(int x,int y,int w)
{
    e[num].ed=y;e[num].flow=w;e[num].next=head[x];head[x]=num++;
    e[num].ed=x;e[num].flow=0;e[num].next=head[y];head[y]=num++;
}
void Addedge(int x,int y)
{
    E[tot].ed=y;E[tot].next=first[x];first[x]=tot++;
}
int dfs(int u,int minflow)  
{  
    if(u==end)return minflow;  
    int i,v,f,min_dis=ans-1,flow=0;  
    for(i=head[u];i!=-1;i=e[i].next)  
    {  
        v=e[i].ed;  
        if(e[i].flow<=0)continue;  
        if(dis[v]+1==dis[u])  
        {  
            f=dfs(v,e[i].flow>minflow-flow?minflow-flow:e[i].flow);  
            e[i].flow-=f;  
            e[i^1].flow+=f;  
            flow+=f;  
            if(flow==minflow)break;  
            if(dis[start]>=ans)return flow;  
        }  
        min_dis=min_dis>dis[v]?dis[v]:min_dis;  
    }  
    if(flow==0)  
    {  
        if(--gap[dis[u]]==0)  
            dis[start]=ans;  
        dis[u]=min_dis+1;  
        gap[dis[u]]++;  
    }  
    return flow;  
}
int isap()
{
    int maxflow=0;
    memset(gap,0,sizeof(gap));
    memset(dis,0,sizeof(dis));
    gap[0]=ans;
    while(dis[start]<ans)
        maxflow+=dfs(start,inf);
    return maxflow;
}
bool judge(int D)
{
    memset(head,-1,sizeof(head));
    num=0;
    int i,j;
    for(i=1;i<=n;i++)
    {
        addedge(start,i,D);
        addedge(i+n,end,D);
        addedge(i,i+2*n,K);
        for(j=1;j<=n;j++)
        {
            if(map[i][j])
                addedge(i,j+n,1);
            else addedge(i+2*n,j+n,1);
        }
    }
    if(isap()==n*D)
        return true;
    return false;
}
int main()
{
    int i,j,k,m,F,t,x,y,flag;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&n,&m,&K,&F);
        tot=0;start=0;end=n+n+n+1;ans=end+1;
        memset(first,-1,sizeof(first));
        memset(map,false,sizeof(map));
        for(i=1;i<=n;i++)
            f[i]=i;
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            Addedge(x,y);
            map[x][y]=true;
        }
        while(F--)
        {
            scanf("%d%d",&x,&y);
            if(find(x)!=find(y))
                f[find(x)]=find(y);
        }
        for(i=1;i<=n;i++)
        {
            for(j=i+1;j<=n;j++)
            {
                if(find(i)!=find(j))continue;
                for(k=first[i];k!=-1;k=E[k].next)
                    map[j][E[k].ed]=true;
                for(k=first[j];k!=-1;k=E[k].next)
                    map[i][E[k].ed]=true;                    
            }
        }
        int L=1,R=n,mid;
        flag=0;
        while(L<=R)
        {
            mid=(L+R)>>1;
            if(judge(mid))
            {
                flag=mid;
                L=mid+1;
            }
            else R=mid-1;
        }
        printf("%d\n",flag);
    }
    return 0;
}



你可能感兴趣的:(编程,算法,百度,ACM,网络流)