def parse(inFile):
[P, W] = inFile.getInts()
wormholes = [[int(num) for num in word.split(",")] for word in inFile.getWords()]
return (P,wormholes)
class Queue:
def __init__(self, x):
self.q = x
self.qat = 0
self.qlen = len(x)
def pop(self):
self.qat += 1
return self.q[self.qat - 1]
def elements(self):
while (not self.empty()):
yield self.pop()
def push(self, x):
self.q.append(x)
self.qlen += 1
def empty(self):
return self.qat == self.qlen
def solve((numPlanets, wormholes)):
print "There are %d planets." % numPlanets
nbs = [[] for i in xrange(numPlanets)]
adj = [[False for i in xrange(numPlanets)] for j in xrange(numPlanets)]
for i in xrange(len(wormholes)):
[p0,p1] = wormholes[i]
adj[p0][p1] = True
adj[p1][p0] = True
nbs[p0].append([p1,i])
nbs[p1].append([p0,i])
d0 = [numPlanets+1] * numPlanets
d0[0] = 0
q = Queue([0])
while (not (q.empty())):
qi = q.pop()
for nb in [z[0] for z in nbs[qi]]:
if (d0[nb] > d0[qi] + 1):
d0[nb] = d0[qi] + 1
q.push(nb)
d1 = [numPlanets+1] * numPlanets
d1[1] = 0
q = Queue([1])
while (not (q.empty())):
qi = q.pop()
for nb in [z[0] for z in nbs[qi]]:
if (d1[nb] > d1[qi] + 1):
d1[nb] = d1[qi] + 1
q.push(nb)
threats = [[-1,-1,-1] for w in wormholes]
n0 = len(nbs[0])
q = Queue([])
for i in nbs[0]:
[j,w] = i
if d1[j] == d1[0] - 1:
threats[w] = [j,0,n0+len([k for k in nbs[j] if not adj[0][k[0]]])]
q.push(w)
rec = 0
if d0[1] == 1:
rec = n0 + 1
for qi in q.elements():
[j,i,t] = threats[qi]
for p in nbs[j]:
[dest,num] = p
if (dest == 1):
rec = max(rec, t)
if (d0[dest] == d0[j] + 1) and (d1[dest] == d1[j] - 1):
if threats[num][0] == -1:
q.push(num)
threats[num] = max(threats[num], [dest,j,t+len([k for k in nbs[dest] if not (adj[i][k[0]] or adj[j][k[0]])])])
return " ".join([str(d0[1] - 1),str(rec-d0[1])])
if __name__ == "__main__":
from GCJ import GCJ
GCJ(parse, solve, "/Users/lpebody/gcj/2011_round2/", "d").run()
ZGVmIHBhcnNlKGluRmlsZSk6CiAgICBbUCwgV10gPSBpbkZpbGUuZ2V0SW50cygpCiAgICB3b3JtaG9sZXMgPSBbW2ludChudW0pIGZvciBudW0gaW4gd29yZC5zcGxpdCgiLCIpXSBmb3Igd29yZCBpbiBpbkZpbGUuZ2V0V29yZHMoKV0KICAgIHJldHVybiAoUCx3b3JtaG9sZXMpCgpjbGFzcyBRdWV1ZToKICAgIGRlZiBfX2luaXRfXyhzZWxmLCB4KToKICAgICAgICBzZWxmLnEgPSB4CiAgICAgICAgc2VsZi5xYXQgPSAwCiAgICAgICAgc2VsZi5xbGVuID0gbGVuKHgpCiAgICAKICAgIGRlZiBwb3Aoc2VsZik6CiAgICAgICAgc2VsZi5xYXQgKz0gMQogICAgICAgIHJldHVybiBzZWxmLnFbc2VsZi5xYXQgLSAxXQogICAgCiAgICBkZWYgZWxlbWVudHMoc2VsZik6CiAgICAgICAgd2hpbGUgKG5vdCBzZWxmLmVtcHR5KCkpOgogICAgICAgICAgICB5aWVsZCBzZWxmLnBvcCgpCgogICAgZGVmIHB1c2goc2VsZiwgeCk6CiAgICAgICAgc2VsZi5xLmFwcGVuZCh4KQogICAgICAgIHNlbGYucWxlbiArPSAxCgogICAgZGVmIGVtcHR5KHNlbGYpOgogICAgICAgIHJldHVybiBzZWxmLnFhdCA9PSBzZWxmLnFsZW4KCmRlZiBzb2x2ZSgobnVtUGxhbmV0cywgd29ybWhvbGVzKSk6CiAgICBwcmludCAiVGhlcmUgYXJlICVkIHBsYW5ldHMuIiAlIG51bVBsYW5ldHMKICAgIG5icyA9IFtbXSBmb3IgaSBpbiB4cmFuZ2UobnVtUGxhbmV0cyldCiAgICBhZGogPSBbW0ZhbHNlIGZvciBpIGluIHhyYW5nZShudW1QbGFuZXRzKV0gZm9yIGogaW4geHJhbmdlKG51bVBsYW5ldHMpXQogICAgZm9yIGkgaW4geHJhbmdlKGxlbih3b3JtaG9sZXMpKToKICAgICAgICBbcDAscDFdID0gd29ybWhvbGVzW2ldCiAgICAgICAgYWRqW3AwXVtwMV0gPSBUcnVlCiAgICAgICAgYWRqW3AxXVtwMF0gPSBUcnVlCiAgICAgICAgbmJzW3AwXS5hcHBlbmQoW3AxLGldKQogICAgICAgIG5ic1twMV0uYXBwZW5kKFtwMCxpXSkKICAgIGQwID0gW251bVBsYW5ldHMrMV0gKiBudW1QbGFuZXRzCiAgICBkMFswXSA9IDAKICAgIHEgPSBRdWV1ZShbMF0pCiAgICB3aGlsZSAobm90IChxLmVtcHR5KCkpKToKICAgICAgICBxaSA9IHEucG9wKCkKICAgICAgICBmb3IgbmIgaW4gW3pbMF0gZm9yIHogaW4gbmJzW3FpXV06CiAgICAgICAgICAgIGlmIChkMFtuYl0gPiBkMFtxaV0gKyAxKToKICAgICAgICAgICAgICAgIGQwW25iXSA9IGQwW3FpXSArIDEKICAgICAgICAgICAgICAgIHEucHVzaChuYikKICAgIGQxID0gW251bVBsYW5ldHMrMV0gKiBudW1QbGFuZXRzCiAgICBkMVsxXSA9IDAKICAgIHEgPSBRdWV1ZShbMV0pCiAgICB3aGlsZSAobm90IChxLmVtcHR5KCkpKToKICAgICAgICBxaSA9IHEucG9wKCkKICAgICAgICBmb3IgbmIgaW4gW3pbMF0gZm9yIHogaW4gbmJzW3FpXV06CiAgICAgICAgICAgIGlmIChkMVtuYl0gPiBkMVtxaV0gKyAxKToKICAgICAgICAgICAgICAgIGQxW25iXSA9IGQxW3FpXSArIDEKICAgICAgICAgICAgICAgIHEucHVzaChuYikKICAgIAogICAgdGhyZWF0cyA9IFtbLTEsLTEsLTFdIGZvciB3IGluIHdvcm1ob2xlc10KICAgIG4wID0gbGVuKG5ic1swXSkKICAgIHEgPSBRdWV1ZShbXSkKICAgIGZvciBpIGluIG5ic1swXToKICAgICAgICBbaix3XSA9IGkKICAgICAgICBpZiBkMVtqXSA9PSBkMVswXSAtIDE6CiAgICAgICAgICAgIHRocmVhdHNbd10gPSBbaiwwLG4wK2xlbihbayBmb3IgayBpbiBuYnNbal0gaWYgbm90IGFkalswXVtrWzBdXV0pXQogICAgICAgICAgICBxLnB1c2godykKICAgIHJlYyA9IDAKICAgIGlmIGQwWzFdID09IDE6CiAgICAgICAgcmVjID0gbjAgKyAxCiAgICBmb3IgcWkgaW4gcS5lbGVtZW50cygpOgogICAgICAgIFtqLGksdF0gPSB0aHJlYXRzW3FpXQogICAgICAgIGZvciBwIGluIG5ic1tqXToKICAgICAgICAgICAgW2Rlc3QsbnVtXSA9IHAKICAgICAgICAgICAgaWYgKGRlc3QgPT0gMSk6CiAgICAgICAgICAgICAgICByZWMgPSBtYXgocmVjLCB0KQogICAgICAgICAgICBpZiAoZDBbZGVzdF0gPT0gZDBbal0gKyAxKSBhbmQgKGQxW2Rlc3RdID09IGQxW2pdIC0gMSk6CiAgICAgICAgICAgICAgICBpZiB0aHJlYXRzW251bV1bMF0gPT0gLTE6CiAgICAgICAgICAgICAgICAgICAgcS5wdXNoKG51bSkKICAgICAgICAgICAgICAgIHRocmVhdHNbbnVtXSA9IG1heCh0aHJlYXRzW251bV0sIFtkZXN0LGosdCtsZW4oW2sgZm9yIGsgaW4gbmJzW2Rlc3RdIGlmIG5vdCAoYWRqW2ldW2tbMF1dIG9yIGFkaltqXVtrWzBdXSldKV0pCiAgICByZXR1cm4gIiAiLmpvaW4oW3N0cihkMFsxXSAtIDEpLHN0cihyZWMtZDBbMV0pXSkKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBmcm9tIEdDSiBpbXBvcnQgR0NKCiAgICBHQ0oocGFyc2UsIHNvbHZlLCAiL1VzZXJzL2xwZWJvZHkvZ2NqLzIwMTFfcm91bmQyLyIsICJkIikucnVuKCkK