BWInf 2011, pertanyaan 5: Kota kembar

8

Ini adalah tantangan yang semula merupakan tas untuk Bundatik Jerman Informatik (kompetisi federal ilmu komputer [?]), Kompetisi untuk siswa sekolah menengah. Berbeda dengan pertanyaan awal, di mana Anda harus menemukan solusi yang baik dan menulis beberapa dokumentasi, saya ingin Anda bermain golf ini. Saya mencoba mereplikasi pertanyaan sebaik mungkin:

Tantangan

Banyak kota di Eropa memiliki apa yang disebut kota kembar . Tahun ini, ada Jubilee khusus di mana setiap pasangan kota kembar di UE menyelenggarakan festival untuk merayakan kemitraan mereka. Untuk memastikan bahwa tidak ada kota yang menyelenggarakan terlalu banyak festival, setiap kota memiliki batas festival yang dapat diorganisir. Mungkinkah untuk mendistribusikan festival di antara kota-kota kembar sedemikian rupa, sehingga setiap pasangan kota kembar menyelenggarakan satu festival di satu kota dua dan tidak ada kota yang menyelenggarakan lebih banyak festival daripada yang diizinkan? Jika ya, jelaskan caranya.

Ini adalah peta dari beberapa kota, kemitraan mereka dan batasan festival mereka.

kemitraan http://dl.dropbox.com/u/1869832/partnerships.png

Persyaratan

  • Program Anda harus mengakhiri masalah dalam satu menit masing-masing untuk kedua testcases. (Lihat di bawah)
  • Lihat testcases untuk format input.
  • Outputnya harus kosong jika tidak ada solusi dan harus memiliki format berikut: Jika tidak, satu baris untuk setiap pasangan kota kembar, ajika city1menyelenggarakan festival, bsebaliknya.

    <city1>, <city2>, <a/b>
    
  • Solusi dengan jumlah karakter paling sedikit yang memenuhi persyaratan menang. Dalam kasus seri, program yang diajukan menang terlebih dahulu.

  • Aturan golf-aturan biasa berlaku.

Testcases

Tugas asli memiliki dua testcases. Saya telah mengunggahnya di github .

FUZxxl
sumber
Petunjuk: ada pengurangan sederhana untuk integer max-flow.
Peter Taylor
@ Peter, bagaimana dengan pencocokan bipartit?
FUZxxl
Pengurangan adalah sedikit perpanjangan dari pengurangan pencocokan bipartit standar dan harus lebih efisien daripada pengurangan melalui pencocokan bipartit (yang akan mengharuskan mengubah setiap kota menjadi nsimpul, di mana nbatas anggaran kota).
Peter Taylor

Jawaban:

2

Python, 380 karakter

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)

Kode ini menggunakan algoritma aliran maksimum push-relabel -style . N[x]adalah jumlah pihak yang diizinkan pada x, X[x]adalah daftar kota mitra yang saat ini dijadwalkan untuk dihosting di x(yang mungkin lebih lama daripada N[x]selama algoritma), dan H[x]merupakan ketinggian berlabel x. Untuk kota yang berlangganan berlebih, kami mendorong salah satu pihak yang dijadwalkan ke kota mitra yang lebih rendah, atau menaikkan tinggi.

Keith Randall
sumber
2

C #, 1016 992 916 karakter

Membutuhkan 4 detik untuk saya di set tes besar; kinerja dapat dengan mudah ditingkatkan banyak dengan membuat Xsebuah HashSet<s>daripada 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]]);}}

Ini menggunakan reduksi ke aliran maks yang saya sebutkan sebelumnya di komentar. Verteksnya adalah

  1. Sumber Sdan wastafel yang baru dibuat T.
  2. Kemitraan.
  3. Kota.

Tepinya adalah

  1. Dari sumber ke setiap kemitraan dengan kapasitas aliran 1.
  2. Dari setiap kemitraan ke setiap kota dalam kemitraan dengan kapasitas aliran 1.
  3. Dari setiap kota ke wastafel dengan kapasitas aliran yang sama dengan anggaran kota itu.

Algoritma ini adalah Ford-Fulkerson dengan DFS. Jelas apriori bahwa setiap jalur penambahan akan meningkatkan aliran sebesar 1, sehingga optimalisasi golf untuk menghilangkan perhitungan aliran jalur tidak memiliki efek negatif pada kinerja.

Ada kemungkinan optimisasi lain dengan membuat asumsi seperti "Nama file input tidak akan pernah sama dengan nama kota", tapi itu IMO agak rapuh.

Peter Taylor
sumber