結果

問題 No.2403 "Eight" Bridges of Königsberg
ユーザー detteiuu
提出日時 2025-03-03 00:45:46
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 364 ms / 2,000 ms
コード長 2,238 bytes
コンパイル時間 530 ms
コンパイル使用メモリ 82,376 KB
実行使用メモリ 122,752 KB
最終ジャッジ日時 2025-03-03 00:45:54
合計ジャッジ時間 7,803 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 31
権限があれば一括ダウンロードができます

ソースコード

diff #

class UnionFind:
    def __init__(self,n):
        self.n = n
        self.parent_size = [-1]*n
 
    def leader(self,a):
        if self.parent_size[a] < 0:
            return a
        self.parent_size[a] = self.leader(self.parent_size[a])
        return self.parent_size[a]
 
    def merge(self,a,b):
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return 
        if abs(self.parent_size[x]) < abs(self.parent_size[y]):
            x, y = y, x
        self.parent_size[x] += self.parent_size[y]
        self.parent_size[y] = x
        return 
 
    def same(self,a,b):
        return self.leader(a) == self.leader(b)
 
    def size(self,a):
        return abs(self.parent_size[self.leader(a)])
 
    def groups(self):
        result = [[] for _ in range(self.n)]
        for i in range(self.n):
            result[self.leader(i)].append(i)
        return [r for r in result if r != []]

N, M = map(int, input().split())
edge = [list(map(int, input().split())) for _ in range(M)]

INF = 10**18

cnt = [[0]*2 for _ in range(N)]
UF = UnionFind(N)
for u, v in edge:
    u, v = u-1, v-1
    cnt[u][0] += 1
    cnt[v][1] += 1
    UF.merge(u, v)

def DP(A):
    dp = [[INF]*(1<<2) for _ in range(len(A)+1)]
    dp[0][0] = 0
    for i in range(len(A)):
        a = A[i]
        for bit in range(1<<2):
            if dp[i][bit] == INF:
                continue
            dp[i+1][bit] = min(dp[i+1][bit], dp[i][bit]+abs(cnt[a][0]-cnt[a][1]))
            if not 1<<0 & bit:
                if cnt[a][0]-1 >= cnt[a][1]:
                    dp[i+1][bit|1<<0] = min(dp[i+1][bit|1<<0], dp[i][bit]+cnt[a][0]-1-cnt[a][1])
                else:
                    dp[i+1][bit|1<<0] = min(dp[i+1][bit|1<<0], dp[i][bit]+cnt[a][1]+1-cnt[a][0])
            if not 1<<1 & bit:
                if cnt[a][1]-1 >= cnt[a][0]:
                    dp[i+1][bit|1<<1] = min(dp[i+1][bit|1<<1], dp[i][bit]+cnt[a][1]-1-cnt[a][0])
                else:
                    dp[i+1][bit|1<<1] = min(dp[i+1][bit|1<<1], dp[i][bit]+cnt[a][0]+1-cnt[a][1])
    return min(dp[-1][0], dp[-1][3])//2

ans = 0
G = UF.groups()
for g in G:
    ans += DP(g)
for g in G:
    if 2 <= len(g) or 1 <= max(cnt[g[0]]):
        ans += 1
ans -= 1

print(ans)
0