結果
| 問題 | No.654 Air E869120 |
| コンテスト | |
| ユーザー |
asugen0402
|
| 提出日時 | 2019-02-05 17:16:22 |
| 言語 | C (gcc 13.3.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 9,071 bytes |
| 記録 | |
| コンパイル時間 | 680 ms |
| コンパイル使用メモリ | 30,464 KB |
| 実行使用メモリ | 68,992 KB |
| 最終ジャッジ日時 | 2025-01-03 00:01:32 |
| 合計ジャッジ時間 | 26,026 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 24 WA * 5 TLE * 6 |
コンパイルメッセージ
main.c: In function ‘fMain’:
main.c:340:9: warning: ignoring return value of ‘fgets’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
340 | fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:351:17: warning: ignoring return value of ‘fgets’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
351 | fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ソースコード
#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;
}
asugen0402