#include #include #include #include #include #include #include #include #include #include #include const char* inname = "mbone.in"; #ifdef TUMTEST #define DBG cerr #else #define DBG if (0) cerr #endif ifstream in(inname); #define out cout FILE* fin; template T min(T a, T b) { return (a < b) ? a : b; } template T max(T a, T b) { return (a > b) ? a : b; } #define MAXL 50 template class List { public: int first, last; T buffer[MAXL]; List() : first(0), last(0) { } void clear() { first = last = 0; } int count() { return (last - first + MAXL) % MAXL; } int append(const T &t) { int i = last; buffer[last] = t; last = (last + 1) %MAXL; return i; } void remove(int i) { int j = (first + i) % MAXL, k = (j + 1) % MAXL; while(k != last) { buffer[j] = buffer[k]; j = (j + 1) % MAXL; k = (k + 1) % MAXL; } last = (last - 1 + MAXL) % MAXL; } T &operator[](int i) { return buffer[(first + i) % MAXL]; } int index(const T &t) { for(int i = first; i != last; i = (i + 1) % MAXL) if(buffer[i] == t) return i; return -1; } int operator==(const List &l) { assert(&l != 0); return 1; } }; #define NOCONNECT INT_MAX / 2; #define MAXV 10 #define MAXA 50000 int iCount; char islands[MAXV][21]; int getIsland(char *s) { for(int i = 0; i < iCount; i++) if(0 == strcmp(s, islands[i]) ) return i; return -1; } List hostIndex; List theIsland; List groupIndex; List > theGroup; List emptyG; int edges[MAXV][MAXV]; int oCount; int output[MAXA][3]; void init() { iCount = 0; hostIndex.clear(); theIsland.clear(); groupIndex.clear(); theGroup.clear(); for(int i = 0; i < MAXV; i++) for(int j = 0; j < MAXV; j++) if( i == j ) edges[i][j] = 0; else edges[i][j] = NOCONNECT; oCount = 0; } void calcAllPaths() { int i, j, k; for(i = 0; i < iCount; i++) for(j = 0; j < iCount; j++) for(k = 0; k < iCount; k++) if(edges[j][k] > edges[j][i] + edges[i][k]) { edges[j][k] = edges[j][i] + edges[i][k]; } } bool readMBone() { int i, j, n, host; int tCount = 0; int tmpThresh[MAXV * MAXV]; int tmpSrc[MAXV * MAXV]; char tmpName[MAXV * MAXV][21]; in >> iCount; if(0 == iCount) return false; for(i = 0; i < iCount; i++) { in >> islands[i] >> n; for(j = 0; j < n; j++) { in >> ws; if('H' == in.get()) { in >> host; hostIndex.append(host); theIsland.append(i); } else { tmpSrc[tCount] = i; in >> tmpThresh[tCount] >> tmpName[tCount]; tCount++; } } } for(i = 0; i < tCount; i++) edges[tmpSrc[i]][getIsland(tmpName[i])] = tmpThresh[i]; return true; } void joinGroup(int host, int group) { int gInd = groupIndex.index(group); if( -1 == gInd ) { gInd = groupIndex.append(group); int i = theGroup.append(emptyG); theGroup[i].clear(); DBG << "added Group " << group << endl; } theGroup[gInd].append(host); } void leaveGroup(int host, int group) { int gInd = groupIndex.index(group); theGroup[gInd].remove(theGroup[gInd].index(host)); DBG << theGroup[gInd].count() << endl; if(theGroup[gInd].count() == 0) { groupIndex.remove(gInd); theGroup.remove(gInd); DBG << "removed Group " << group << endl; } } int mySort(const void *a, const void *b) { int *ia = (int *) a; int *ib = (int *) b; if(ia[0] < ib[0]) return -1; else if(ia[0] > ib[0]) return 1; else { if(ia[1] < ib[1]) return -1; else if(ia[1] > ib[1]) return 1; } return 0; } int main() { fin = fopen(inname, "r"); int aCount, i, j, host, group, pID, ttl; int gInd, netw = 1; char c; while(true) { init(); if(!readMBone()) break; for(i = 0; i < iCount; i++) { for(j = 0; j < iCount; j++) DBG << edges[i][j] << " "; DBG << endl; } DBG << endl; calcAllPaths(); for(i = 0; i < iCount; i++) { for(j = 0; j < iCount; j++) DBG << edges[i][j] << " "; DBG << endl; } in >> aCount; for(i = 0; i < aCount; i++) { in >> ws >> c >> host >> group; if( 'J' == c ) joinGroup(host, group); else if( 'L' == c ) leaveGroup(host, group); else { int iFrom = theIsland[hostIndex.index(host)]; in >> pID >> ttl; gInd = groupIndex.index(group); List *g = &theGroup[gInd]; for(j = 0; j < g->count(); j++) { int hostTo = (*g)[j]; int iTo = theIsland[hostIndex.index( hostTo )]; int l = ttl - edges[iFrom][iTo]; DBG << iFrom << " " << iTo << " " << hostTo << " " << pID << " " << ttl << " " << edges[iFrom][iTo] << " " << l << endl; if(l >= 0) { output[oCount][0] = hostTo; output[oCount][1] = pID; output[oCount][2] = l; oCount++; } } } } qsort(output, oCount, 3*sizeof(int), mySort); out << "Network #" << netw++ << endl; for(i = 0; i < oCount; i++) out << output[i][0] << " " << output[i][1] << " " << output[i][2] << endl; out << endl; DBG << groupIndex.count() << endl; DBG << theGroup.count() << endl; } return 0; }