hdu 3081&hdu 3277 (最大流)

来源:互联网 发布:焦土抗战 知乎 编辑:程序博客网 时间:2024/04/27 03:34

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;}



原创粉丝点击