#include #include #include #include #include #include #include // 内部定数 #define D_ON 1 // 汎用フラグ - ON #define D_OFF 0 // 汎用フラグ - OFF #define D_FLY_MAX 1000 // 最大飛行数 #define D_ETIME_MAX 1000000000 // 最大到着時間 #define D_VTX_MAX (D_FLY_MAX * 2 + 5) // 最大頂点数((出発時間 + 到着時間) * 飛行数 + 街1 + 街N) #define D_HEAP_MAX D_VTX_MAX // 最大ヒープ数 // 内部構造体 - 飛行情報 typedef struct Fly { int miTFNo; // 出発街 0~ int miTTNo; // 到着街 0~ int miTimeS; // 出発時間 int miTimeE; // 到着時間+乗り継ぎ時間 int miHCnt; // 飛行人数 } Fly; // 内部構造体 - 頂点情報 typedef struct Vtx { int miTNo; // 街 int miTime; // 時間 long long ml1Cap[D_VTX_MAX]; // 容量[接続先頂点] int miDone; // 処理済フラグ } Vtx; // 内部構造体 - ヒープ情報 typedef struct Heap { long long mlFlow; // 流量 int mi1TNo[D_VTX_MAX]; // 街(ルート) int miTCnt; // 街(ルート)数 } Heap; // 内部変数 static FILE *szpFpI; // 入力 static Fly sz1Fly[D_FLY_MAX]; // 飛行情報 static int siFCnt; // 飛行情報数 static Vtx sz1Vtx[D_VTX_MAX]; // 頂点 static int siVCnt; // 頂点数 static Heap sz1Heap[D_HEAP_MAX]; // ヒープ static int siHCnt; // ヒープ数 // 内部変数 - テスト用 #ifdef D_TEST static int siRes; static FILE *szpFpA; #endif // ソート関数 - 街昇順 - 時間昇順 int fSortFnc( const void *pzpVal1 // 値1 , const void *pzpVal2 // 値2 ) { Vtx *lzpVal1 = (Vtx *)pzpVal1; Vtx *lzpVal2 = (Vtx *)pzpVal2; // 街昇順 if (lzpVal1->miTNo > lzpVal2->miTNo) { return 1; } else if (lzpVal1->miTNo < lzpVal2->miTNo) { return -1; } // 時間昇順 if (lzpVal1->miTime > lzpVal2->miTime) { return 1; } else if (lzpVal1->miTime < lzpVal2->miTime) { return -1; } return 0; } // 頂点 - 検索 int fSrhVNo( int piTNo // 街 0~ , int piTime // 時間 ) { int i; for (i = 0; i < siVCnt; i++) { if (sz1Vtx[i].miTNo == piTNo) { if (sz1Vtx[i].miTime == piTime) { return i; } } } return -1; } // ヒープ - 比較 - 流量降順 int fHeapCmp( int piNo1 // 配列番号1 0~ , int piNo2 // 配列番号2 0~ ) { // 流量降順 if (sz1Heap[piNo1].mlFlow < sz1Heap[piNo2].mlFlow) { return 1; } else if (sz1Heap[piNo1].mlFlow > sz1Heap[piNo2].mlFlow) { return -1; } return 0; } // ヒープ - 親子関係チェック // 戻り値:[>=0]:変更した子の配列番号 [-1]:変更なし int fHeapChk( int piPNo // 親の配列番号 0~ ) { int liRet; // 最小値 int liMNo = piPNo; // 左の子と比較 int liCNo = piPNo * 2 + 1; if (liCNo < siHCnt) { liRet = fHeapCmp(liMNo, liCNo); if (liRet == 1) { liMNo = liCNo; } } // 右の子と比較 liCNo = piPNo * 2 + 2; if (liCNo < siHCnt) { liRet = fHeapCmp(liMNo, liCNo); if (liRet == 1) { liMNo = liCNo; } } // 自分が最小値であるかチェック if (piPNo == liMNo) { return -1; } // 値の交換 Heap lzWork; memcpy(&lzWork, &sz1Heap[liMNo], sizeof(Heap)); memcpy(&sz1Heap[liMNo], &sz1Heap[piPNo], sizeof(Heap)); memcpy(&sz1Heap[piPNo], &lzWork, sizeof(Heap)); return liMNo; } // ヒープ - キュー追加 int fHeapEnqueue( long long plFlow // 流量 , int *pipTNo // 街(ルート) , int piTCnt // 街(ルート)数 ) { int liRet; // 末尾に追加 sz1Heap[siHCnt].mlFlow = plFlow; memcpy(sz1Heap[siHCnt].mi1TNo, pipTNo, sizeof(int) * piTCnt); sz1Heap[siHCnt].miTCnt = piTCnt; siHCnt++; // 親子関係チェック int liNo = siHCnt - 1; while (1) { // 親の配列番号 liNo = (liNo - 1) / 2; // 親子関係チェック liRet = fHeapChk(liNo); if (liRet < 0) { break; } } return 0; } // ヒープ - キュー取得 int fHeapDequeue( Heap *pzpRet // 取得先 ) { // データ数 if (siHCnt < 1) { return -1; } // 取得 memcpy(pzpRet, &sz1Heap[0], sizeof(Heap)); siHCnt--; // データ数 if (siHCnt < 1) { return 0; } // 末尾を先頭へ memcpy(&sz1Heap[0], &sz1Heap[siHCnt], sizeof(Heap)); // 親子関係チェック int liNo = 0; while (liNo >= 0) { liNo = fHeapChk(liNo); } return 0; } // 最大流 - 取得 long long fGetMaxFlow( int piVSNo // 始点 , int piVENo // 終点 ) { int i, liRet; long long llSum = 0; while (1) { // 処理済フラグ - 初期化 for (i = 0; i < siVCnt; i++) { sz1Vtx[i].miDone = D_OFF; } // ヒープ - 初期化 siHCnt = 0; int li1Route[D_VTX_MAX]; li1Route[0] = piVSNo; fHeapEnqueue(LLONG_MAX, li1Route, 1); // 1フロー - 取得 Heap lzHeap; while (1) { // キュー取得 liRet = fHeapDequeue(&lzHeap); if (liRet != 0) { break; } // 現在頂点 int liVNo = lzHeap.mi1TNo[lzHeap.miTCnt - 1]; // 処理済フラグ - セット sz1Vtx[liVNo].miDone = D_ON; // 到着チェック if (liVNo == piVENo) { break; } // キュー追加 for (i = 0; i < siVCnt; i++) { // 処理済フラグ - チェック if (sz1Vtx[i].miDone != D_OFF) { continue; } // 流量 long long llFlow = sz1Vtx[liVNo].ml1Cap[i]; if (llFlow < 1) { // なし continue; } if (llFlow > lzHeap.mlFlow) { llFlow = lzHeap.mlFlow; } // 下位へ lzHeap.mi1TNo[lzHeap.miTCnt] = i; fHeapEnqueue(llFlow, lzHeap.mi1TNo, lzHeap.miTCnt + 1); } } if (liRet != 0) { // なし break; } // 流量 - 加算 llSum += lzHeap.mlFlow; // 容量 - 加算・減算 for (i = 0; i < lzHeap.miTCnt - 1; i++) { sz1Vtx[lzHeap.mi1TNo[i]].ml1Cap[lzHeap.mi1TNo[i + 1]] -= lzHeap.mlFlow; sz1Vtx[lzHeap.mi1TNo[i + 1]].ml1Cap[lzHeap.mi1TNo[i]] += lzHeap.mlFlow; } } return llSum; } // 実行メイン int fMain( int piTNo // テスト番号 1~ ) { int i; char lc1Buf[1024], lc1Out[1024]; // データ - 初期化 memset(sz1Vtx, 0, sizeof(sz1Vtx)); // 頂点 // 入力 - セット #ifdef D_TEST sprintf(lc1Buf, ".\\Test\\T%d.txt", piTNo); szpFpI = fopen(lc1Buf, "r"); sprintf(lc1Buf, ".\\Test\\A%d.txt", piTNo); szpFpA = fopen(lc1Buf, "r"); siRes = 0; #else szpFpI = stdin; #endif // 街数・飛行数・乗り継ぎ時間 - 取得 int liTCnt, liTimeA; fgets(lc1Buf, sizeof(lc1Buf), szpFpI); sscanf(lc1Buf, "%d%d%d", &liTCnt, &siFCnt, &liTimeA); // 頂点 - 街1 sz1Vtx[0].miTNo = 0; sz1Vtx[0].miTime = -1; siVCnt = 1; // 飛行 - 取得 for (i = 0; i < siFCnt; i++) { int liFNo, liTNo, liTimeS, liTimeE, liHCnt; fgets(lc1Buf, sizeof(lc1Buf), szpFpI); sscanf(lc1Buf, "%d%d%d%d%d", &liFNo, &liTNo, &liTimeS, &liTimeE, &liHCnt); liFNo--; liTNo--; liTimeE += liTimeA; // 到着時間チェック if (liTimeE > D_ETIME_MAX) { continue; } // 飛行情報 - セット sz1Fly[i].miTFNo = liFNo; sz1Fly[i].miTTNo = liTNo; sz1Fly[i].miTimeS = liTimeS; sz1Fly[i].miTimeE = liTimeE; sz1Fly[i].miHCnt = liHCnt; // 頂点 - 追加 sz1Vtx[siVCnt].miTNo = liFNo; sz1Vtx[siVCnt].miTime = liTimeS; siVCnt++; sz1Vtx[siVCnt].miTNo = liTNo; sz1Vtx[siVCnt].miTime = liTimeE; siVCnt++; } // 頂点 - 街N sz1Vtx[siVCnt].miTNo = liTCnt - 1; sz1Vtx[siVCnt].miTime = INT_MAX; siVCnt++; // 頂点 - ソート qsort(sz1Vtx, siVCnt, sizeof(Vtx), fSortFnc); // 頂点 - 容量 - セット - 同一街 for (i = 0; i < siVCnt - 1; i++) { if (sz1Vtx[i].miTNo == sz1Vtx[i + 1].miTNo) { sz1Vtx[i].ml1Cap[i + 1] = LLONG_MAX; } } // 頂点 - 容量 - セット - 飛行 for (i = 0; i < siFCnt; i++) { // 頂点 - 取得 int liVFNo = fSrhVNo(sz1Fly[i].miTFNo, sz1Fly[i].miTimeS); // 出発 int liVTNo = fSrhVNo(sz1Fly[i].miTTNo, sz1Fly[i].miTimeE); // 到着 // 容量 - セット sz1Vtx[liVFNo].ml1Cap[liVTNo] = sz1Fly[i].miHCnt; } // 最大流 - 取得 long long llMax = fGetMaxFlow(0, siVCnt - 1); // 結果 - セット sprintf(lc1Out, "%lld\n", llMax); // 結果 - 表示 #ifdef D_TEST fgets(lc1Buf, sizeof(lc1Buf), szpFpA); if (strcmp(lc1Buf, lc1Out)) { siRes = -1; } #else printf("%s", lc1Out); #endif // 残データ有無 #ifdef D_TEST lc1Buf[0] = '\0'; fgets(lc1Buf, sizeof(lc1Buf), szpFpA); if (strcmp(lc1Buf, "")) { siRes = -1; } #endif // テストファイルクローズ #ifdef D_TEST fclose(szpFpI); fclose(szpFpA); #endif // テスト結果 #ifdef D_TEST if (siRes == 0) { printf("OK %d\n", piTNo); } else { printf("NG %d\n", piTNo); } #endif return 0; } int main() { #ifdef D_TEST int i; for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) { fMain(i); } #else fMain(0); #endif return 0; }