您的位置:首页 > 其它

POJ 2289 Jamis's Contact Group

2010-11-27 16:14 411 查看
一开始题目意思理解错了,其实是要求每个group最多能有几个人,我去找最大group的编号了。。。囧,size居然被我理解成那个意思。。。

正确理解题目意思后,二分答案,枚举最大值,源点与每个人连容量为1的边,每个人与他可以呆的组连一条边,然后将每个组与汇点连线,容量为枚举的最大值,如果满流就减小最大值,否则扩大最大值

代码:

#include<iostream>
using namespace std;
#define min(x,y) (x)<(y)?(x):(y)
#define inf 99999999
#define MAX 1600
struct node
{
int x,y,c,op,next;
}g[1000000];
int map[MAX][605],dis[MAX],pre[MAX];
int num[MAX],cur[MAX],adj[MAX],in[MAX];
int m,n,S,T,vn,max_flow,e,l,r;
void add(int x,int y,int c)
{
e++;
g[e].x=x; g[e].y=y; g[e].c=c; g[e].op=e+1; g[e].next=adj[x]; adj[x]=e;
e++;
g[e].x=y; g[e].y=x; g[e].c=0; g[e].op=e-1; g[e].next=adj[y]; adj[y]=e;
}
void relabel(int k)
{
int i,mm=vn;
cur[k]=adj[k];
for(i=adj[k];i;i=g[i].next)
{
if(g[i].c>0)
mm=min(mm,dis[g[i].y]);
}
dis[k]=mm+1;
}
void change()
{
int nf=inf,i;
for(i=T;i!=S;i=g[pre[i]].x)
{
nf=min(nf,g[pre[i]].c);
}
for(i=T;i!=S;i=g[pre[i]].x)
{
g[pre[i]].c-=nf;
g[g[pre[i]].op].c+=nf;
}
max_flow+=nf;
}
void sap()
{
int i;
for(i=1;i<=vn;i++)
{
dis[i]=0;
num[i]=0;
cur[i]=adj[i];
}
num[0]=vn;
i=S;
while(dis[S]<vn)
{
for(;cur[i];cur[i]=g[cur[i]].next)
{
if(g[cur[i]].c>0&&dis[i]==dis[g[cur[i]].y]+1)
break;
}
if(!cur[i])
{
num[dis[i]]--;
if(num[dis[i]]==0)
break;
relabel(i);
num[dis[i]]++;
if(i!=S)
i=g[pre[i]].x;
}
else
{
pre[g[cur[i]].y]=cur[i];
i=g[cur[i]].y;
if(i==T)
{
change();
i=S;
}
}
}
}
bool check(int limit)
{
int i,j;
e=0;
memset(adj,0,sizeof(adj));
S=n+m+1;
T=n+m+2;
vn=T;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(map[i][j])
{
add(i,n+j,1);
}
}
for(i=1;i<=n;i++)
add(S,i,1);
for(i=1;i<=m;i++)
{
add(i+n,T,limit);
}
max_flow=0;
sap();
if(max_flow==n)
return true;
else
return false;
}
void partition()
{
int i,mid,ans;
l=0;
r=-1;
for(i=1;i<=m;i++)
if(in[i]>r)
r=in[i];
while(l<=r)
{
mid=(l+r)/2;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
printf("%d/n",ans);
}
int main()
{
int i,t;
char name[20],c;
while(scanf("%d%d",&n,&m)&&m&&n)
{
memset(map,0,sizeof(map));
memset(in,0,sizeof(in));
for(i=1;i<=n;i++)
{
scanf("%s",&name);
t=0;
getchar();
while(scanf("%c",&c))
{
if(c==10)
{
map[i][++t]=1;
in[t]++;
t=0;
break;
}
if(c==' ')
{
map[i][++t]=1;
in[t]++;
t=0;
}
else
t=t*10+c-'0';
}
}
partition();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: