«问题描述:
假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为
ri(i=1,2,3...m), 。会议餐厅共有n张餐桌,每张餐桌可容纳c i(i=1,2...n) 个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,
给出满足要求的代表就餐方案。
«编程任务:
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
«数据输入:
由文件roundtable.in提供输入数据。文件第1行有2 个正整数m和n,m表示单位数,n表
示餐桌数,1<=m<=150, 1<=n<=270。文件第2 行有m个正整数,分别表示每个单位的代表
数。文件第3 行有n个正整数,分别表示每个餐桌的容量。
«结果输出:
程序运行结束时,将代表就餐方案输出到文件roundtable.out中。如果问题有解,在文件第
1 行输出1,否则输出0。接下来的m行给出每个单位代表的就餐桌号。如果有多个满足要
求的方案,只要输出1 个方案。
输入文件示例 输出文件示例
roundtable.in
4 5
4 5 3 5
3 5 2 6 4
roundtable.out
1
1 2 4 5
1 2 3 4 5
2 4 5
1 2 3 4 5
/*自己YY了一个贪心,觉得貌似靠谱,没想到就AC了。*/ #include<cstdio> #include<iostream> #include<queue> #include<algorithm> #define N 1010 using namespace std; int a[N][N],n,m; struct node{ int num,id; bool operator< (node s1) const { return s1.num>num; } };node group[N],b[N]; priority_queue<node> q; bool cmp(const node&s1,const node&s2){return s1.num>s2.num;} int main(){ scanf("%d%d",&m,&n); if(m>n){printf("0\n");return 0;} for(int i=1;i<=m;i++){ scanf("%d",&group[i].num); group[i].id=i; } for(int i=1;i<=n;i++){ int x;scanf("%d",&x); q.push((node){x,i}); } sort(group+1,group+m+1,cmp); node x; for(int i=1;i<=m;i++){ int id=group[i].id; for(int j=1;j<=group[i].num;j++){ x=q.top();q.pop(); if(x.num<1){printf("0\n");return 0;} a[id][++a[id][0]]=x.id; b[a[id][0]]=(node){x.num-1,x.id}; } for(int j=1;j<=a[id][0];j++) q.push(b[j]); } printf("1\n"); for(int i=1;i<=m;i++){ for(int j=1;j<=a[i][0];j++) printf("%d ",a[i][j]); printf("\n"); } return 0; }
/*网络流做法,比贪心要慢不少。*/ #include<iostream> #include<cstdio> #include<queue> #include<cstring> #define N 510 #define inf 1000000000 using namespace std; int a[N],b[N],m,n,sum; int head[N],dis[N],cnt=1,S,T,edge[N][N]; struct node{int v,f,pre;}e[N*N]; void add(int u,int v,int f){ e[++cnt].v=v;e[cnt].f=f;e[cnt].pre=head[u];head[u]=cnt; e[++cnt].v=u;e[cnt].f=0;e[cnt].pre=head[v];head[v]=cnt; } bool bfs(){ memset(dis,-1,sizeof(dis)); queue<int> q;q.push(S);dis[S]=0; while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].pre) if(e[i].f&&dis[e[i].v]==-1){ dis[e[i].v]=dis[u]+1; q.push(e[i].v); } } return dis[T]!=-1; } int dinic(int x,int f){ int rest=f; if(x==T)return f; for(int i=head[x];i;i=e[i].pre){ if(!e[i].f||dis[e[i].v]<=dis[x])continue; int t=dinic(e[i].v,min(rest,e[i].f)); if(!t) dis[e[i].v]=-1; e[i].f-=t; e[i^1].f+=t; rest-=t; } return f-rest; } int main(){ scanf("%d%d",&m,&n);S=0;T=n+m+1; for(int i=1;i<=m;i++)scanf("%d",&a[i]),sum+=a[i]; for(int i=1;i<=n;i++)scanf("%d",&b[i]); for(int i=1;i<=m;i++)add(S,i,a[i]); for(int i=1;i<=n;i++)add(i+m,T,b[i]); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ edge[i][j]=cnt+1; add(i,j+m,1); } int maxflow=0; while(bfs()) maxflow+=dinic(S,inf); if(maxflow==sum) printf("1\n"); else printf("0\n"); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) if(!e[edge[i][j]].f) printf("%d ",j); printf("\n"); } return 0; }