1. 程式人生 > >[洛谷P3254] [網絡流24題] 圓桌遊戲

[洛谷P3254] [網絡流24題] 圓桌遊戲

i++ out n) esp d+ truct 方案 scanf space

Description

假設有來自m 個不同單位的代表參加一次國際會議。每個單位的代表數分別為ri (i =1,2,……,m)。

會議餐廳共有n 張餐桌,每張餐桌可容納ci (i =1,2,……,n)個代表就餐。

為了使代表們充分交流,希望從同一個單位來的代表不在同一個餐桌就餐。試設計一個算法,給出滿足要求的代表就餐方案。

對於給定的代表數和餐桌數以及餐桌容量,編程計算滿足要求的代表就餐方案。

Input

第1 行有2 個正整數m 和n,m 表示單位數,n 表示餐桌數,1<=m<=150, 1<=n<=270。

第2 行有m 個正整數,分別表示每個單位的代表數。

第3 行有n 個正整數,分別表示每個餐桌的容量。

Output

如果問題有解,第1 行輸出1,否則輸出0。接下來的m 行給出每個單位代表的就餐桌號。如果有多個滿足要求的方案,只要輸出1 個方案。

Sample Input

4 5
4 5 3 5
3 5 2 6 4

Sample Output

1
1 2 4 5
1 2 3 4 5
2 4 5
1 2 3 4 5


想法

因為是網絡流24題,所以上來我先想的是怎麽用可愛的最小割。
沒想出來,於是仔細分析了一下題意。
發現,誒,好像貪心就可以啊……
單位代表數排個序,每個餐桌剩余容量排個序,先做剩余容量多的餐桌。
就A了……

之後又想了想網絡流怎麽做。
S向每個單位連容量為單位代表數的邊,每個單位向所有餐桌連容量為1的邊,每個餐桌向T連容量為餐桌容量的邊。
跑一邊最大流,看S發出的邊是否都滿流就完了。

這可真是一道辣雞題……


代碼

(貪心)

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 275;
const int M = 155;

struct data{
    int v,id;
    bool operator < (const data &b) const{
        return v>b.v;     
    }
}d[N],r[M];

int c[M][N],w[M];
int n,m;

int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++){
        scanf("%d",&r[i].v);
        r[i].id=i;
        w[i]=r[i].v;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&d[i].v);
        d[i].id=i;
    }
    
    int flag=1;
    sort(r+1,r+1+m);
    for(int i=1;i<=m;i++){
       sort(d+1,d+1+n);
       for(int j=1;j<=r[i].v;j++){
           if(!d[j].v) break;
           c[r[i].id][j]=d[j].id;
           d[j].v--;
       }
       if(!c[r[i].id][r[i].v]) { flag=0; break; }
    }
    
    if(flag==0) printf("0\n");
    else {
        printf("1");
        for(int i=1;i<=m;i++){
            printf("\n%d",c[i][1]);
            for(int j=2;j<=w[i];j++)
                printf(" %d",c[i][j]);      
        }
    }
    
    return 0;    
}

[洛谷P3254] [網絡流24題] 圓桌遊戲