結果

問題 No.654 Air E869120
ユーザー asugen0402asugen0402
提出日時 2019-02-05 17:16:22
言語 C
(gcc 12.3.0)
結果
TLE  
実行時間 -
コード長 9,071 bytes
コンパイル時間 780 ms
コンパイル使用メモリ 32,364 KB
実行使用メモリ 43,168 KB
最終ジャッジ日時 2023-08-30 23:52:26
合計ジャッジ時間 4,672 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 9 ms
34,904 KB
testcase_01 AC 9 ms
34,844 KB
testcase_02 AC 9 ms
34,828 KB
testcase_03 AC 9 ms
34,832 KB
testcase_04 AC 9 ms
34,720 KB
testcase_05 AC 10 ms
34,708 KB
testcase_06 AC 10 ms
34,888 KB
testcase_07 AC 10 ms
34,724 KB
testcase_08 AC 9 ms
34,804 KB
testcase_09 AC 9 ms
34,744 KB
testcase_10 TLE -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
testcase_36 -- -
testcase_37 -- -
testcase_38 -- -
testcase_39 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#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			// <I> 値1
	, const void *pzpVal2		// <I> 値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					// <I> 街 0~
	, int piTime				// <I> 時間
)
{
	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					// <I> 配列番号1 0~
	, int piNo2					// <I> 配列番号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					// <I> 親の配列番号 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			// <I> 流量
	, int *pipTNo				// <I> 街(ルート)
	, int piTCnt				// <I> 街(ルート)数
)
{
	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				// <O> 取得先
)
{
	// データ数
	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					// <I> 始点
	, int piVENo				// <I> 終点
)
{
	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					// <I> テスト番号 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;
}

0