poj2289:http://poj.org/problem?id=2289
题意:给定一个规模为n的名单,要将名单中的人归到m个组中,给出每个人可能的分组号,需要确定一种分配方案,是的最大规模的组最小。
题解:很明显的二分。然后把人和组都拆点即可。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<queue> 6 #define INF 100000000 7 using namespace std; 8 const int N=3205; 9 const int M=1000000; 10 struct Node{ 11 int v; 12 int f; 13 int next; 14 }edge[M]; 15 int n,m,u,v,cnt,sx,ex; 16 int head[N],pre[N]; 17 int val[N][40];//根据题目要求申请 18 void init(){ 19 cnt=0; 20 memset(head,-1,sizeof(head)); 21 } 22 void add(int u,int v,int w){ 23 edge[cnt].v=v; 24 edge[cnt].f=w; 25 edge[cnt].next=head[u]; 26 head[u]=cnt++; 27 edge[cnt].f=0; 28 edge[cnt].v=u; 29 edge[cnt].next=head[v]; 30 head[v]=cnt++; 31 } 32 bool BFS(){ 33 memset(pre,0,sizeof(pre)); 34 pre[sx]=1; 35 queue<int>Q; 36 Q.push(sx); 37 while(!Q.empty()){ 38 int d=Q.front(); 39 Q.pop(); 40 for(int i=head[d];i!=-1;i=edge[i].next ){ 41 if(edge[i].f&&!pre[edge[i].v]){ 42 pre[edge[i].v]=pre[d]+1; 43 Q.push(edge[i].v); 44 } 45 } 46 } 47 return pre[ex]>0; 48 } 49 int dinic(int flow,int ps){ 50 int f=flow; 51 if(ps==ex)return f; 52 for(int i=head[ps];i!=-1;i=edge[i].next){ 53 if(edge[i].f&&pre[edge[i].v]==pre[ps]+1){ 54 int a=edge[i].f; 55 int t=dinic(min(a,flow),edge[i].v); 56 edge[i].f-=t; 57 edge[i^1].f+=t; 58 flow-=t; 59 if(flow<=0)break; 60 } 61 62 } 63 if(f-flow<=0)pre[ps]=-1; 64 return f-flow; 65 } 66 int solve(){ 67 int sum=0; 68 while(BFS()) 69 sum+=dinic(INF,sx); 70 return sum; 71 } 72 char str[20]; 73 int ans[N][N]; 74 int tot[N],top; 75 void build(int mid){ 76 init(); 77 for(int i=1;i<=n;i++){ 78 for(int j=1;j<=tot[i];j++){ 79 add(i+n,ans[i][j]+2*n,1); 80 } 81 add(i,i+n,1); 82 add(0,i,1); 83 } 84 for(int i=1;i<=m;i++){ 85 add(i+2*n,i+2*n+m,mid); 86 add(i+2*n+m,2*m+2*n+1,INF); 87 } 88 } 89 int as,temp; 90 int main() { 91 while(~scanf("%d%d",&n,&m)&&n) { 92 init(); 93 as=0; 94 for(int i=1;i<=n;i++){ 95 scanf("%s",str); 96 top=0; 97 while(getchar()!=‘\n‘){ 98 scanf("%d",&temp); 99 //printf("**%d\n",temp); 100 ans[i][++top]=++temp; 101 } 102 tot[i]=top; 103 } 104 int l=0,r=n; 105 sx=0,ex=2*n+2*m+1; 106 while(l<=r){ 107 int mid=(l+r)/2; 108 build(mid); 109 if(solve()==n){ 110 r=mid-1; 111 as=mid; 112 } 113 else 114 l=mid+1; 115 } 116 printf("%d\n",as); 117 118 } 119 return 0; 120 }
Jamie's Contact Groups
时间: 2024-10-12 16:19:53