圆桌聚餐(cogs 729)

«问题描述:
假设有来自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;
}

 

 
posted @ 2017-02-27 22:21  karles~  阅读(484)  评论(2编辑  收藏  举报