結果
| 問題 | 
                            No.2642 Don't cut line!
                             | 
                    
| コンテスト | |
| ユーザー | 
                             | 
                    
| 提出日時 | 2024-02-19 22:25:04 | 
| 言語 | PyPy3  (7.3.15)  | 
                    
| 結果 | 
                             
                                AC
                                 
                             
                            
                         | 
                    
| 実行時間 | 648 ms / 4,000 ms | 
| コード長 | 3,069 bytes | 
| コンパイル時間 | 218 ms | 
| コンパイル使用メモリ | 82,332 KB | 
| 実行使用メモリ | 157,568 KB | 
| 最終ジャッジ日時 | 2024-09-29 03:35:06 | 
| 合計ジャッジ時間 | 15,870 ms | 
| 
                            ジャッジサーバーID (参考情報)  | 
                        judge3 / judge4 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 3 | 
| other | AC * 33 | 
ソースコード
import sys
from itertools import permutations
from heapq import heappop,heappush
from collections import deque
import random
import bisect
input = lambda :sys.stdin.readline().rstrip()
mi = lambda :map(int,input().split())
li = lambda :list(mi())
class UnionFindVerSize():
    def __init__(self, N):
        self._parent = [n for n in range(0, N)]
        self._size = [1] * N
        self.group = N
    def find_root(self, x):
        if self._parent[x] == x: return x
        self._parent[x] = self.find_root(self._parent[x])
        return self._parent[x]
    def unite(self, x, y):
        gx = self.find_root(x)
        gy = self.find_root(y)
        if gx == gy: return
        self.group -= 1
        if self._size[gx] < self._size[gy]:
            self._parent[gx] = gy
            self._size[gy] += self._size[gx]
        else:
            self._parent[gy] = gx
            self._size[gx] += self._size[gy]
    def get_size(self, x):
        return self._size[self.find_root(x)]
    def is_same_group(self, x, y):
        return self.find_root(x) == self.find_root(y)
    
def solve(N,M,C,Edge):
    Edge.sort(key=lambda e:e[2])
    uf = UnionFindVerSize(N)
    MST_edge = [[] for v in range(N)]
    total_cost = 0
    res = -1
    rest_Edge = []
    for u,v,w,p in Edge:
        if not uf.is_same_group(u,v):
            uf.unite(u,v)
            MST_edge[u].append((v,w))
            MST_edge[v].append((u,w))
            total_cost += w
            res = max(res,p)
        else:
            rest_Edge.append((u,v,w,p))
    if total_cost > C:
        return -1
    
    K = 17
    parent = [[(-1,-1)]*N for i in range(K)]
    dep = [0] * N
    deq = deque([0])
    while deq:
        v = deq.popleft()
        for nv,w in MST_edge[v]:
            if nv == parent[0][v][0]:
                continue
            parent[0][nv] = (v,w)
            dep[nv] = dep[v] + 1
            deq.append(nv)
    
    for k in range(1,K):
        for v in range(N):
            pv,nw = parent[k-1][v]
            if pv!=-1:
                ppv,nnw = parent[k-1][pv]
                parent[k][v] = (ppv,max(nnw,nw))
    
    def maxi_w_on_path(u,v):
        if dep[u] > dep[v]:
            u,v = v,u
        
        diff = dep[v] - dep[u]
        res = -1
        for k in range(K)[::-1]:
            if diff>>k & 1:
                pv,w = parent[k][v]
                res = max(res,w)
                v = pv
        
        if u == v:
            return res
        
        for k in range(K)[::-1]:
            pu,uw = parent[k][u]
            pv,vw = parent[k][v]
            if pu!=pv:
                u,v = pu,pv
                res = max(res,uw,vw)
        
        pu,uw = parent[0][u]
        pv,vw = parent[0][v]
        return max(res,uw,vw)
    
    for u,v,w,p in rest_Edge:
        tmp_cost = total_cost - maxi_w_on_path(u,v) + w
        if tmp_cost <= C:
            res = max(res,p)
    
    return res
    
N,M,C = mi()
Edge = []
for _ in range(M):
    u,v,w,p = mi()
    Edge.append((u-1,v-1,w,p))
print(solve(N,M,C,Edge))