結果
| 問題 | No.3699 引き抜き交渉 |
| コンテスト | |
| ユーザー |
titia
|
| 提出日時 | 2026-11-01 04:59:13 |
| 言語 | PyPy3 (8.0.1 + ACL) |
| 結果 |
AC
不安定
|
| 実行時間 | 92 ms / 2,000 ms |
| + 307µs | |
| コード長 | 3,577 bytes |
| 記録 | |
| コンパイル時間 | 99 ms |
| コンパイル使用メモリ | 64,096 KB |
| 実行使用メモリ | 62,272 KB |
| 最終ジャッジ日時 | 2026-11-01 04:59:17 |
| 合計ジャッジ時間 | 3,465 ms |
|
ジャッジサーバーID (参考情報) |
judge2_0 / judge7_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 15 |
ソースコード
import sys
input = sys.stdin.readline
N,M=list(map(int,input().split()))
# Dinic法高速化バージョン、
# https://atcoder.jp/contests/awc0071/submissions/80438454
from collections import deque
V=N+2
start=N
goal=N+1
# G[v] : 頂点 v から出る辺の番号一覧
# TO[e] : 辺 e の行き先
# CAP[e] : 辺 e の残余容量
# TO[G[u]],CAP[G[u]]により、行き先と容量を見る。
G=[[] for i in range(V)]
TO=[]
CAP=[]
SUM=0
for i in range(N):
x,y=list(map(int,input().split()))
if x==y:
SUM+=x
continue
elif x>y:
SUM+=x
u,v,c=start,i,x-y
e=len(TO)
G[u].append(e)
G[v].append(e^1)
TO.append(v)
TO.append(u)
CAP.append(c)
CAP.append(0)
else:
SUM+=y
u,v,c=i,goal,y-x
e=len(TO)
G[u].append(e)
G[v].append(e^1)
TO.append(v)
TO.append(u)
CAP.append(c)
CAP.append(0)
for i in range(M):
x,y,z=list(map(int,input().split()))
x-=1
y-=1
u,v,c=x,y,z
e=len(TO)
G[u].append(e)
G[v].append(e^1)
TO.append(v)
TO.append(u)
CAP.append(c)
CAP.append(0)
u,v,c=y,x,z
e=len(TO)
G[u].append(e)
G[v].append(e^1)
TO.append(v)
TO.append(u)
CAP.append(c)
CAP.append(0)
ANS=0
while True:
# まずBFSでレベルグラフを作る
DIS=[-1]*V
Q=deque([start])
DIS[start]=0
while Q:
x=Q.popleft()
# ゴールまでの距離が確定していたら、
# それと同じ距離以上の頂点は探索しない
if DIS[goal] != -1 and DIS[x] >= DIS[goal]:
break
for e in G[x]:
if CAP[e]==0:
continue
to=TO[e]
if DIS[to]==-1:
DIS[to]=DIS[x]+1
Q.append(to)
if DIS[goal]==-1:
break
# it[v] : 頂点 v で次に調べる辺の位置
it = [0] * V
# レベルグラフ上でDFS。
# goalからstartに向かって探索する
MINCOST=[1<<30]*V
ROUTE=[-1]*V
while True:
STACK=[goal]
found=False
while STACK:
NOW=STACK[-1]
if NOW==start:
# 増加路が見つかった
cost=MINCOST[start]
ANS+=cost
# goalからstartに戻りながら容量を更新
i=goal
while i!=start:
e=ROUTE[i]
j=TO[e^1]
# 飽和する辺なら、この辺の探索位置を進める
if CAP[e]==cost:
it[i]+=1
CAP[e]-=cost
CAP[e^1]+=cost
i=j
found=True
break
# NOWに入ってくる辺を逆向きに調べる
while it[NOW]<len(G[NOW]):
r=G[NOW][it[NOW]]
e=r^1
prev=TO[r]
if CAP[e]>0 and DIS[prev]+1==DIS[NOW]:
break
it[NOW]+=1
if it[NOW]<len(G[NOW]):
r=G[NOW][it[NOW]]
e=r^1
prev=TO[r]
ROUTE[NOW]=e
MINCOST[prev]=min(MINCOST[NOW],CAP[e])
STACK.append(prev)
else:
STACK.pop()
if STACK:
it[STACK[-1]]+=1
if not found:
break
print(SUM-ANS)
titia