BZOJ 1305

为什么是男孩女孩互相喜欢,好像要发生什么了不得的大事→→


e,说正事,这是一道网络流最大流的题。
先要二分,网上题解某人说不用,那时我too young。
结果TLE了那么1000多ms。。。

/**************************************************************
    Problem: 1305
    User: fantasticwtl
    Language: C++
    Result: Time_Limit_Exceed
****************************************************************/

唉。。。二分大法好,之后嘛拆点,如果(这里啥都没有→)男生i与女生j相互喜欢则男生i.x与女生j.x,连一条流量为1的边(只能跳一次),不然则i.y与j.y连一条边,因为k的原因,我们再把男生的x,y两两相连,流量为k,女生也一样,最后一步是源点S与男生的x连边,流量即为二分的值,女生的x与汇点T连边,流量同上,之后跑dinic验证即可。

这个。。。程序里,男生的x是1~n,y是n+1~2*n,女生的x是2*n+1~3*n,y是3*n+1~4*n。

几组或许能帮到你的数据:

Input1
3 0
YXX
YXX
YYY

Output1
0

Input2
5 3
YYYYY
YYYYY
YYYXX
YYYXX
XXXYY

Output2
5

啦啦啦,贴代码╮(╯_╰)╭

/**************************************************************
    Problem: 1305
    User: fantasticwtl
    Language: C++
    Result: Accepted
    Time:84 ms
    Memory:1792 kb
****************************************************************/

#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<algorithm>  
#include<iostream>  
#define inf 1000000000  
#define maxn 310  
#define maxm 12010  

using namespace std;  

int head[maxn],to[maxm],next[maxm],c[maxm],q[maxn],d[maxn];  
int n,m,num,s,t,k;  
char s1[maxn];  
int a[maxn][maxn];  

void addedge(int x,int y,int z)  
{  
    num++;to[num]=y;c[num]=z;next[num]=head[x];head[x]=num;  
    num++;to[num]=x;c[num]=0;next[num]=head[y];head[y]=num;  
}  

bool bfs()  
{  
    memset(d,-1,sizeof(d));  
    int l=0,r=1;  
    q[1]=s;d[s]=0;  
    while (l<r)  
    {  
        int x=q[++l];  
        for (int p=head[x];p;p=next[p])  
          if (c[p] && d[to[p]]==-1)  
          {  
            d[to[p]]=d[x]+1;  
            q[++r]=to[p];  
          }  
    }  
    if (d[t]==-1) return 0;  
    else return 1;  
}  

int find(int x,int low)  
{  
    if (x==t || low==0) return low;  
    int totflow=0;  
    for (int p=head[x];p;p=next[p])  
      if (c[p] && d[to[p]]==d[x]+1)  
      {  
        int a=find(to[p],min(low,c[p]));  
        c[p]-=a;c[p^1]+=a;  
        totflow+=a;low-=a;  
        if (low==0) return totflow;  
      }  
    if (low) d[x]=-1;  
    return totflow;  
}  

bool Dinic(int x)  
{  
    num=1;  
    memset(head,0,sizeof(head));  
    memset(c,0,sizeof(c));  
    s=0;t=4*n+1;  
    for (int i=1;i<=n;i++) addedge(s,i,x),addedge(i,n+i,k),addedge(2*n+i,3*n+i,k),addedge(3*n+i,t,x);  
    for (int i=1;i<=n;i++)  
      for (int j=1;j<=n;j++)  
        if (a[i][j]) addedge(i,3*n+j,1);  
        else addedge(n+i,2*n+j,1);  
    int ans=0;  
    while (bfs()) ans+=find(s,inf);  
    if (ans==n*x) return 1;  
    else return 0;  
}  

int main()  
{  
    scanf("%d%d",&n,&k);  
    for (int i=1;i<=n;i++)  
    {  
        scanf("%s",s1+1);  
        for (int j=1;j<=n;j++)  
          if (s1[j]=='Y') a[i][j]=1; else a[i][j]=0;  
    }  //输入部分
    int l=1,r=n,ans=0;  
    while (l<=r)  //二分
    {  
        int mid=(l+r)/2;  
        if (Dinic(mid)) l=mid+1,ans=mid;  //Dinic验证
        else r=mid-1;  
    }  
    printf("%d\n",ans);  
    return 0;  
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值