Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
用递归写的dinic应该不比用栈模拟的更差啊,但是为啥还是超时啊?#include<iostream> #include<string.h> #include<stdio.h> #include<queue> using namespace std; #define inf 10000000 #define N 4010 #define M 200 struct edge { int sta; int end; int cap; int next; }E[N*M*2]; int edgenum,head[N+M],restmp; int dis[N]; int rank[N][M],numb[M]; int n,b; void init() { edgenum=0; memset(head,-1,sizeof(head)); } void addedge(int sta,int end,int cap) { E[edgenum].sta=sta; E[edgenum].end=end; E[edgenum].cap=cap; E[edgenum].next=head[sta]; head[sta]=edgenum++; } void build(int sta,int end,int low,int high) { int i,j; init(); for(i=1;i<=n;i++) { addedge(sta,i,1); addedge(i,sta,0); } for(i=n+1;i<=n+b;i++) { addedge(i,end,numb[i-n]); addedge(end,i,0); } for(i=1;i<=n;i++) { for(j=low;j<=high;j++) { addedge(i,n+rank[i][j],inf); addedge(n+rank[i][j],i,0); } } } int BFS(int sta,int end) { queue<int>que; memset(dis,0,sizeof(dis)); que.push(sta); dis[sta]=1; while(!que.empty()) { int front=que.front(); que.pop(); if(front==end)return 1; for(int i=head[front];i!=-1;i=E[i].next) { int to=E[i].end; if(E[i].cap>0&&dis[to]==0) { que.push(to); dis[to]=dis[front]+1; } } } return 0; } int DFS(int sta,int end,int cur,int minx) { if(cur==end) { restmp+=minx; return minx; } for(int i=head[cur];i!=-1;i=E[i].next) { if(E[i].cap>0&&dis[E[i].end]==dis[cur]+1) { int t=DFS(sta,end,E[i].end,min(minx,E[i].cap)); if(t>0) { E[i].cap-=t; E[i^1].cap+=t; if(cur!=sta)return t; } } } return 0; } int dinic(int sta,int end,int low,int high) { int flow=0; build(sta,end,low,high); while(BFS(sta,end)) { restmp=0; DFS(sta,end,sta,inf); if(restmp==0)break; flow+=restmp; } return flow==n; } int erfen(int sta,int end) { int left=1,right=1; int mid,i; while(left<=right&&right<=b) { mid=(left+right)/2; int ff=0; for(i=1;i<=b-mid+1;i++) { if(dinic(sta,end,i,i+mid-1)) { ff=1; break; } } if(ff) right=mid-1; else left=mid+1; } return left; } int main() { scanf("%d%d",&n,&b); { int i,j; int sta=0,end=n+b+1;//源点和汇点 for( i=1;i<=n;i++) { for( j=1;j<=b;j++) scanf("%d",&rank[i][j]); } for(i=1;i<=b;i++) scanf("%d",&numb[i]); printf("%d\n",erfen(sta,end)); } return 0; } //因为每次找到了增广路之后更新流量都必须退到源点。 Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator