#454. Minimum Or Spanning Tree
阿新 • • 發佈:2022-04-04
#454. Minimum Or Spanning Tree
題目描述
給出\(n\)個點, \(m\)條邊的無向圖, 每條邊連線\(u,v\)兩個端點,邊權為\(w\), 求圖的生成樹的最小代價。
在這道題中, 我們定義一棵生成樹的代價為他所有邊的邊權按位或得到的值。
輸入格式
第一行兩個數字 \(n\) 和 \(m , n\) 表示點數,$m $表示圖的邊數。
接下來 \(m\) 行 , 每行三個整數 \(u,v,w\),表示點 \(u\) 和點\(v\) 之間存在一條邊權為 \(w\) 的邊。
輸出格式
一行, 描述生成樹的最小代價。
樣例輸入
5 7 4 2 7 2 5 8 3 4 2 3 2 1 2 4 2 4 1 2 1 2 2
樣例輸出
10
資料規模
所有資料保證 \(1≤u,v≤n≤2⋅10^5,n−1≤m≤4⋅10^5,1≤w≤10^9\)且至少存在一棵生成樹。
題目分析
先假設\(ans\)為最大值,按位列舉看看當前位是否能為\(0\),把為\(0\)的放在一起,通過並查集檢測是否構成聯通圖。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5+7; struct Edge { ll s,f; ll val; }; inline int read(){ int This=0,F=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') F=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ This=(This<<1)+(This<<3)+ch-'0'; ch=getchar(); } return This*F; } int fa[N]; inline int find(int x) { if(x==fa[x]) return x; fa[x] = find(fa[x]); return fa[x]; } inline void unoin(Edge x) { ll x_fa = find(x.s); ll y_fa = find(x.f); fa[x_fa] = y_fa; } inline bool check(int n) { int t = find(1); for(int i = 1 ; i <= n ; i++) if(find(i)!=t) return 0; return 1; } int main() { // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); int n,m; scanf("%d%d",&n,&m); vector<Edge>e; for(int i = 1 ; i <= m ; i++) { ll s = read(),f= read(),val= read(); e.push_back({s,f,val}); } ll ans = (1ll<<32)-1; for(int i = 31 ; i>=0 ; i--) { ans -= (1ll<<i); vector<Edge>te; memset(fa,0,sizeof(fa)); for(int i = 1 ; i <= n ; i++) fa[i] = i; for(int j = 0 ; j < e.size() ; j++) { if((e[j].val | ans) <= ans) { //希望篩出該位為0 te.push_back(e[j]); unoin(e[j]); } } if(check(n)) e = te; else ans += (1ll<<i); } printf("%lld",ans); return 0; }