BWInf 2011、質問5:ツインタウン


8

これは、もともとドイツ語TASた課題ですBundeswettbewerb Informatikは(コンピュータサイエンスの連邦競技[?])、高校生のための競争。元の質問とは対照的に、適切な解決策を見つけてドキュメントを作成する必要がある場合は、これを利用してほしい。私は質問をできるだけよく再現するようにしています:

チャレンジ

ヨーロッパの多くの町には、いわゆるツインタウンがあります。今年は特別なジュビリーがあり、EUのツインタウンの各ペアがパートナーシップを祝うフェスティバルを開催します。どの都市でも多くのフェスティバルを開催する必要がないようにするために、各都市には主催できるフェスティバルの数に制限があります。ツインタウンの各ペアが1つのフェスティバルを2つのタウンに1つずつ編成し、どのタウンも許可されているよりも多くのフェスティバルを編成しないように、ツインタウンにフェスティバルを分配することは可能ですか?はいの場合、その方法を説明します。

これは、いくつかの町、そのパートナーシップ、およびフェスティバルの限界の地図です。

パートナーシップhttp://dl.dropbox.com/u/1869832/partnerships.png

必要条件

  • プログラムは、両方のテストケースでそれぞれ1分で問題を終了する必要があります。(下記参照)
  • 入力形式については、テストケースを参照してください。
  • 解決策がない場合、出力は空である必要があります。それ以外の場合は、次の形式になります。フェスティバルを開催するa場合は、ツインタウンのペアごとに1行。city1b

    <city1>, <city2>, <a/b>
    
  • 要件を満たす最小の文字数のソリューションが優先されます。引き分けの場合、最初に提出されたプログラムが優先されます。

  • 通常のコードゴルフ規則が適用されます。

テストケース

元のタスクには2つのテストケースがありました。githubにアップロードしました。


ヒント:integer max-flowへの単純な削減があります。
Peter Taylor

@ピーターは二部マッチングについてはどうですか?
FUZxxl

削減は、標準の2部マッチングの削減のわずかな拡張であり、2部マッチングによる削減(各都市をnノードに変更する必要があります。ここnで、都市の予算制限です)よりも効率的です。
Peter Taylor

回答:


2

Python、380文字

import sys
N={};H={};X={}
for L in open(sys.argv[1]):n,x,y=L.split('"');N[x]=int(n);H[x]=0;X[x]=[]
for L in open(sys.argv[2]):s,t=eval(L);X[s]+=[t]
p=1
while p:
 p=0
 for x in N:
  if len(X[x])>N[x]:
   p=1;S=[y for y in X[x]if H[y]<H[x]]
   if S:X[x].remove(S[0]);X[S[0]]+=[x]
   else:H[x]+=1
   if H[x]>2*len(N):sys.exit(0)
for x in N:
 for y in X[x]:print'"%s", "%s", a'%(x,y)

このコードは、push-relabelスタイルの最大フローアルゴリズムを使用します。 N[x]はで許可されるパーティーの数でありxX[x]でホストするように現在スケジュールされているパートナー都市のリストxN[x]アルゴリズム中よりも長い場合があります)でありH[x]、のラベル付き高さですx。オーバーサブスクライブされた都市の場合、スケジュールされたパーティーの1つをより低いパートナー都市にプッシュするか、その高さを上げます。


2

C#、1016 992 916文字

大きなテストセットでは、4秒かかります。でなくを作成XするHashSet<s>と、パフォーマンスを簡単に大幅に改善できますList<s>

using System;using System.Collections.Generic;using System.IO;using System.Linq;using
s=System.String;class D<T>:Dictionary<s,T>{}class E:D<int>{static void Main(s[]x){s
S="",T=">",l;s[]b;D<E>R=new D<E>(),P=new D<E>();R[S]=new E();R[T]=new E();foreach(s L in
File.ReadAllLines(x[0])){b=L.Split('"');s f=b[1];R[T][f]=0;R[f]=new E();P[f]=new
E();R[f][T]=int.Parse(b[0].Trim());}foreach(s L in File.ReadAllLines(x[1])){b=L.Split('"');s
f=b[1],t=b[3],v=f+t;R[v]=new
E();R[v][S]=R[f][v]=R[t][v]=0;P[f][t]=R[S][v]=R[v][f]=R[v][t]=1;}for(;;){List<s>X=new
s[]{S}.ToList(),A=X.ToList();w:while((l=A.Last())!=T){foreach(s t in
R[l].Keys){if(!X.Contains(t)&R[l][t]>0){X.Add(t);A.Add(t);goto
w;}}A.RemoveAt(A.Count-1);if(!A.Any())goto q;}l=S;foreach(s n in
A.Skip(1)){R[l][n]--;R[n][l]++;l=n;}}q:if(R[S].Values.Contains(1))return;foreach(s
f in P.Keys)foreach(s t in P[f].Keys)Console.WriteLine(f+", "+t+", "+"ba"[R[f][f+t]]);}}

これは、コメントで以前に示唆した最大流量の減少を使用しています。頂点は

  1. 新しく生成されたソースSとシンクT
  2. パートナーシップ。
  3. 都市。

エッジは

  1. ソースからフロー容量のある各パートナーシップへ1。
  2. 各パートナーシップから、フローキャパシティのあるパートナーシップの各都市へ1。
  3. 各都市からその都市の予算に等しいフロー容量のシンクまで。

アルゴリズムはDFSを使用したFord-Fulkersonです。各拡張パスがフローを1ずつ増加させることがアプリオリであることは明らかなので、パスのフローの計算を削除するゴルフの最適化はパフォーマンスに悪影響を与えません。

「入力ファイルの名前が都市の名前と同じになることは決してないだろう」などの仮定を行うことにより、他にも可能な最適化がありますが、それはIMOには少し不信感があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.