会员
周边
众包
新闻
博问
闪存
赞助商
Chat2DB
所有博客
当前博客
我的博客
我的园子
账号设置
会员中心
简洁模式
...
退出登录
注册
登录
不是我干的
博客园
首页
新随笔
联系
管理
POJ3189 Steady Cow Assignment 二分枚举+dinic最大流
<p>但是不幸的是,一直超时。</p><p>查不出来是不是我哪写错了。</p><p>还是难道非得sap?</p>
#include<iostream> using namespace std; #define MIN(a,b) (a<b?a:b) #define MAX(a,b) (a>b?a:b) const int N=1005; const int B=25; int n,b; const int inf=99999999; struct Edge { int v,next,w,re; }edge[N*B*2+N*2+4]; int edgehead[N+B]; int k=1; int mat[N][B]; int barn[B]; int level[N+B]; bool visit[N+B]; int que[N+B]; int final; void addedge(int u,int v,int w) { edge[k].v=v; edge[k].w=w; edge[k].re=k+1; edge[k].next=edgehead[u]; edgehead[u]=k++; edge[k].v=u; edge[k].w=0; edge[k].re=k-1; edge[k].next=edgehead[v]; edgehead[v]=k++; } bool bfs() { memset(visit,0,sizeof(visit)); memset(level,0,sizeof(level)); int head=1,tail=1; visit[0]=true; level[0]=0; que[tail++]=0; while(head<tail) { int now=que[head++]; if(now==n+b+1) { return true; } for(int i=edgehead[now];i!=0;i=edge[i].next) { int to=edge[i].v; if(!visit[to]&&edge[i].w>0) { que[tail++]=to; visit[to]=true; level[to]=level[now]+1; } } } return false; } int dinic(int now,int sum) { if(now==final) return sum;//因为是汇点了,return sum则说明流全部消耗。 int os=sum; for(int i=edgehead[now];sum>0&&i!=0;i=edge[i].next)//notice sum>0 { int to=edge[i].v; if(level[to]==level[now]+1&&edge[i].w) { int ret=dinic(to,MIN(sum,edge[i].w));//notice MIN edge[i].w-=ret; edge[edge[i].re].w+=ret; sum-=ret;//这个节点的流被消耗的 此时有可能sum==0 ,故for循环要多一个判断sum>0 } } return os-sum;//返回值必须是消耗的流 } bool solve() { int ans=0; while(bfs()) { ans+=dinic(0,inf); } if(ans<n) return false; else return true; } bool func(int begin,int end)//每次调用都重新构图一次,蛋疼。 { k=1; memset(edge,0,sizeof(edge)); memset(edgehead,0,sizeof(edgehead)); for(int i=1;i<=n;i++) { addedge(0,i,1); } for(int i=1;i<=b;i++) { addedge(n+i,final,barn[i]); } for(int i=1;i<=n;i++) for(int j=begin;j<=end;j++) { addedge(i,mat[i][j]+n,1); } return solve(); } int main() { scanf("%d%d",&n,&b); final=n+b+1; for(int i=1;i<=n;i++) for(int j=1;j<=b;j++) scanf("%d",&mat[i][j]); for(int i=1;i<=b;i++) scanf("%d",&barn[i]); int ans; int s=0,l=b; int mid; while(s<l) { mid=(s+l)/2; bool flag=false; for(int j=1;j+mid<=b;j++) if(func(j,j+mid)) { flag=true; ans=mid; l=mid; break; } if(!flag) { s=mid+1; } } printf("%d\n",ans+1); return 0; }
posted on
2011-09-26 18:04
不是我干的
阅读(
191
) 评论(
0
)
收藏
举报
刷新页面
返回顶部