最大流量+スプリットポイントをダイニングPOJ 3281

ダイニング

制限時間:  2000ミリ秒   メモリの制限:  65536kも
合計提出:  26007   受け入れ:  11411

説明

牛は、細心の注意を食べる人です。それぞれの牛は、特定の食品や飲み物のための好みを持っている、と彼女は何も他の人を消費しません。

ファーマージョンは彼の牛のために素晴らしい食事を調理しているが、彼は自分の好みに対する彼のメニューをチェックするのを忘れました。彼は皆を詰めることができないかもしれませんが、彼はできるだけ多くの牛に食べ物や飲み物の両方の完全な食事を与えたいです。

ファーマージョンは調理している  F  (1≤  F  ≤100)食品の種類をと準備  D  (1≤  D  ≤100)飲み物の種類を。彼の各  Nは、  (1≤  N  ≤100)牛彼女は特定の食べ物を食べたり、特定の飲み物を飲むために喜んでいるかどうかを決定しました。ファーマージョンは両方を取得する牛の数を最大化するために、各牛に食品の種類とドリンクタイプを割り当てる必要があります。

各皿又は飲料は、唯一の牛(食品タイプ2は、牛に割り当てられると、すなわち、他の牛が割り当てられていないことができる食品の種類2)によって消費することができます。

入力

1行目:スリースペースで区切られた整数:  N 、  F 、および  D 
線2 ... N +1:各行  私は  二つの整数で始まり  F I  と  D I 、牛料理の数  私は  好きで、飲み物の数その牛は、  私は  好きです。次の  F  の整数は牛料理表し  、私は  食べるようになる、と  D I  それは牛の飲み物示す次の整数  私は  飲みますが。

出力

行1:彼らの要望に適合飲食物の両方を供給することができる牛の最大数であり、単一の整数

サンプル入力

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

サンプル出力

3

ヒント

3頭の牛を満足させる一つの方法は次のとおりです。 
牛1:食事なしの 
牛2:フード#2、ドリンク#2 
牛3:食品の#1、#1ドリンク 
フード#3、#3を飲む:牛4 
鳩穴原理を教えてくれる食べ物や飲み物の唯一の三種類があるので、私たちは何よりよく行うことができます。他の試験データセットはもちろん、より困難です。
 
入力Nの最初の行、F、D、N、パーソナル発現、食品Fの種類、飲料のDの種類:質問の意味
最初の2つの数のN行から始まる2行目は、食品および飲料の数d_numのF_NUMと量を表し、人々の数の後ろに数F_NUM d_numは、特定の食品や飲み物を表すいくつかのどちらを選択して喜んでです
それぞれの食べ物や飲み物は一部でしかありません、同時にいくつかの人々の願いを満たすためにアップ尋ね
 
 
ソリューション:
ネットワークフロー問題は、キーは、そのようなソースとして、マップを構築することです- >食品- >人- >飲料- >シンクが、それはまた、食べ物や飲み物以上のものを取得したい人に注意を払わなければならないことがありますので、マップであり、ソース内のスプリット  - >食品- >人- >人- >飲料- > T 人々 - >同じ人に同じ人物で、容量は1に設定されている ことに。
 
注:この質問は、EKアルゴリズムはACであるデータ(水)の比較的少量です。EKアルゴリズムを使用してこのトピックやアイデアが、同様hdu4292が終わっていないが、TLEの事前の警告
 
#include <iostreamの> 
する#include <stdio.hに> 
する#include < 文字列・H> 
の#include < ストリング > 
の#include <アルゴリズム> 
の#include <キュー>
 使用して 名前空間STD;
 CONST  INT MAXN = 500 ;
 CONST  INT INF = 0x3FFFFFFF ;
 INT CAP [MAXN] [MAXN]; // エッジの容量を節約する、全くエッジが0に初期化されていない
int型のパス[MAXN]、フロー[MAXN];
 int型 N-; // ポイント番号[0、N]の数、ソースとシンクを含みます。
int型M、FF、D、ST、ENDD、
キュー <INT > P; // キューが時間262msの外側に配置され、機能に内側後322msにではなく、
int型BFS()
{ 
    ながら(!p.empty())
        p.popを(); 
    のmemset(パス、 - 1はsizeof(パス)); // ルート探索前たびに-1に初期化される 
    経路[ST] = 0 ; 
    流れる[ST] = INF; // 無限ストリームを有していてもよく、ソースノードに流れ込む
    p.push(ST );
     一方、(!)p.empty()
    { 
        int型今= p.front(); 
        p.pop(); 
        IF(今== ENDD)
             BREAK ; 
        
        のためのINT I = 0 ; I <= N; I ++)// 変更をここで変更することができるがあれば全ての点、番号出発点を列挙
        {
             IF(ST &&パスI = [I] == - !1。 && CAP [今] [I])
            { 
                フロー[I] [I] =流量[今] <CAP [今]?フロー[今]:CAP [今] [I]; 
                p.push(I)、
                経路[I] = 今; 
            } 
        } 
    } 
    IF(パスは[ENDD] == - 1// すなわちシンクを見つかりませんでした。経路を増強することはできません
        リターン - 。1 ;
     戻り、フロー[ENDD] 
} 
INTをEdmonds_Karp()
{ 
    int型 mx_flow = 0 ;
     int型STEP、POS、事前;
     一方((BFS = STEP())= - !1。 // 工程である残量
    { 
        mx_flow + = ステップと、
        POS = ENDD; // シンクから上のトラフィックポイントを更新
        しながら(POS =!ST)
        { 
            プリ = パス[POS]; 
            CAP [事前] [POS] - = STEP; 
            CAP [POS] [事前] + = ステップと、
            POS = プレ; 
        } 
    }
    リターンmx_flow。
} 
int型のmain()
{ 
    int型の食品、飲料、F_NUM、d_num。
    一方、(〜のscanf(" %D%D%D "、&​​M、&FF&D))
    { 
        memsetの(キャップ、0はsizeof (CAP))。
        N = M * 2 + D + FF + 1 
        ST = 0 ; 
        ENDD = N。
        int型 iは= 1 ; I <= M Iは++ 
        { 
            scanf関数("%D%D "&F_NUM、& d_num);
             のためint型 J = 0 ; J <F_NUM; J ++ 
            { 
                scanf関数(" %のD 、および食品); 
                キャップ[フード] [iが + FF] = 1 ; 
            } 

            INT J = 0 ; J <d_num; J ++ 
            { 
                scanf関数(" %のD "、&ドリンク); 
                キャップ[M + FF + I] [ドリンク+ 2 * Mの+ FF] = 1; 
            } 
        } 

        の場合INT I = 1 ; I <= FF; Iは++)// 各食品のための、唯一の飲み 
            CAPを[ 0 ] [I] = 1 ; 

        のためのINT I = 1。 ;私は= D <; Iを++ 
            CAP [FF + 2 * Mの+ I] [ENDD] = 1 ; 

        のためのINT I = 1 I <= M; I ++の
            CAP [FF + I] [FF + M + I] = 1 ; 

        のprintf(" D%\ N- "、Edmonds_Karp())。
    } 
    戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/-citywall123/p/11335126.html