Solution -「CF 1023F」Mobile Phone Network
阿新 • • 發佈:2020-07-30
\(\mathcal{Description}\)
Link.
有一個 \(n\) 個結點的圖,並給定 \(m_1\) 條無向帶權黑邊,\(m_2\) 條無向無權白邊。你需要為每條白邊指定邊權,最大化其邊權和,並保證 \(m_2\) 條邊都在最小生成樹中。
\(n,m_1,m_2\le5\times10^5\)。
\(\mathcal{Solution}\)
先保證在 \(\text{MST}\) 中的限制——指定所有邊權為 \(0\)。並求出此時的 \(\text{MST}\)。顯然最優情況下,\(\text{MST}\) 的形態和現在一樣。
那麼對於每一條不在 \(\text{MST}\)
複雜度 \(\mathcal O((m_1+m_2)\log(m_1+m_2))\)。
\(\mathcal{Code}\)
#include <cstdio> #include <algorithm> #define ww first #define uu second.first #define vv second.second const int MAXN = 5e5, MAXM = 1e6; int n, m1, m2, m, fa[MAXN + 5]; int ecnt, head[MAXN + 5], trf[MAXN + 5], trc[MAXN + 5], dep[MAXN + 5]; std::pair<int, std::pair<int, int> > eset[MAXM + 5]; bool inmst[MAXM + 5]; struct Edge { int to, cst, nxt; } graph[MAXN * 2 + 5]; inline int rint () { int x = 0; char s = getchar (); for ( ; s < '0' || '9' < s; s = getchar () ); for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' ); return x; } inline void link ( const int s, const int t, const int c ) { graph[++ ecnt] = { t, c, head[s] }; head[s] = ecnt; } inline void init () { for ( int i = 1; i <= n; ++ i ) fa[i] = i; } inline int find ( const int x ) { return x ^ fa[x] ? fa[x] = find ( fa[x] ) : x; } inline bool unite ( int x, int y ) { return ( x = find ( x ) ) ^ ( y = find ( y ) ) ? fa[x] = y, true : false; } inline void DFS ( const int u ) { for ( int i = head[u], v; i; i = graph[i].nxt ) { if ( ( v = graph[i].to ) ^ trf[u] ) { trf[v] = u, trc[v] = graph[i].cst, dep[v] = dep[u] + 1; DFS ( v ); } } } int main () { n = rint (), m = ( m1 = rint () ) + ( m2 = rint () ); init (); for ( int i = 1; i <= m1; ++ i ) { eset[i].uu = rint (), eset[i].vv = rint (); eset[i].ww = 0; } for ( int i = m1 + 1; i <= m; ++ i ) { eset[i].uu = rint (), eset[i].vv = rint (); eset[i].ww = rint (); } std::sort ( eset + 1, eset + m + 1 ); for ( int i = 1, cnt = 0; i <= m; ++ i ) { if ( unite ( eset[i].uu, eset[i].vv ) ) { inmst[i] = true; link ( eset[i].uu, eset[i].vv, eset[i].ww ); link ( eset[i].vv, eset[i].uu, eset[i].ww ); if ( ++ cnt == n - 1 ) break; } } DFS ( 1 ), init (); long long ans = 0; int limited = 0; for ( int i = m1 + 1; i <= m; ++ i ) { if ( inmst[i] ) continue; int u = find ( eset[i].uu ), v = find ( eset[i].vv ), w = eset[i].ww; while ( u ^ v ) { if ( dep[u] < dep[v] ) u ^= v ^= u ^= v; if ( ! trc[u] ) ans += w, ++ limited; int t = find ( trf[u] ); unite ( u, t ), u = t; } } printf ( "%lld\n", limited == m1 ? ans : -1 ); return 0; }