当前位置: 代码迷 >> 综合 >> POJ 2289 二分最大流
  详细解决方案

POJ 2289 二分最大流

热度:2   发布时间:2024-01-20 20:27:59.0

这中类型的题做过两道了,所以一见题就知道思路了。不过这题的输入比较恶心,还好能应付。

本来不想做这题的,但是看到数据也还大1500个点,想用链表试试,先敲了个二维数组,等待TLE的过程中1Y了....

何其蛋疼!1500ms 不算快...

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<map>
#define CC(a) memset(a,0,sizeof(a))
#define FF(i,a) for( int i=0;i<a;i++ )
#define MN 1555
#define ME 555555
template<class T> void inline checkmin( T &a,T b ){ if(a==-1||a>b)a=b; }
using namespace std;struct Edge{int v,c,next;	   
}E[ME];
int N,NE,M,s,t,CAN;
int head[MN],gap[MN],pre[ME],dis[MN],cur[MN];
int maze[MN][MN],cap[MN][MN];void setG()
{CC(cap);map<string,int>map;string str;int num;char c;s=0;t=N+M+1;FF( i,N ){cin>>str;map[str]=M+i+1;num=-1;// people:[M+1,M+N] list:[1,M]while( scanf("%c",&c) ){if( c==' '||c=='\n' ){if( num==-1 ) continue;else cap[num+1][map[str]]++;if( c=='\n' ) break;num=-1;}else{if( num==-1 ) num=c-'0';else num=num*10+c-'0';}}}for( int i=M+1;i<=M+N;i++ )cap[i][t]=1;
}void initG( int mid )
{for( int i=0;i<=t;i++ )for( int j=0;j<=t;j++ )maze[i][j]=cap[i][j];for( int i=1;i<=M;i++ )maze[s][i]=mid;
}bool sap()
{CC(cur);CC(gap);CC(pre);CC(dis);int u=pre[s]=s,maxflow=0,aug=-1;gap[0]=t+1;while( dis[s]<=t ){
loop:for( int v=cur[u];v<=t;v++ )if( maze[u][v]&&dis[u]==dis[v]+1 ){pre[v]=u;cur[u]=v;checkmin(aug,maze[u][v]);u=v;if( v==t ){maxflow+=aug;for( u=pre[u];v!=s;v=u,u=pre[u] ){maze[u][v]-=aug;maze[v][u]+=aug;}aug=-1;}goto loop;}int mind=t;for( int v=0;v<=t;v++ )if( maze[u][v]&&mind>dis[v] ){cur[u]=v;mind=dis[v];}if( --gap[dis[u]]==0 )break;gap[dis[u]=mind+1]++;u=pre[u];}if( maxflow==N ) return true;else return false;
}int main()
{while( scanf("%d%d",&N,&M)!=EOF ){if( N==0&&M==0 )break;setG();int l=1,r=N,m;while( (m=(l+r)/2)&&l<r ){initG(m);if( sap() ) r=m;else l=m+1;}printf( "%d\n",m );}return 0;
}