BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3943
题意:
有n只队伍,每个队伍有一个编号a[i]。
每场比赛有两支队伍参加,然后选一支队伍淘汰。共进行n-1场比赛,然后比赛结束。
若某场比赛是队伍i和j参加,则该场比赛的得分为a[i] xor a[j]。
问最大的总得分。
题解:
每两支队伍(i,j)连一条边,边权为a[i] xor a[j]。
然后求最大生成树即可。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <vector> 6 #define MAX_N 2005 7 8 using namespace std; 9 10 struct Edge 11 { 12 int sour; 13 int dest; 14 long long len; 15 Edge(int _sour,int _dest,long long _len) 16 { 17 sour=_sour; 18 dest=_dest; 19 len=_len; 20 } 21 Edge(){} 22 friend bool operator < (const Edge &a,const Edge &b) 23 { 24 return a.len>b.len; 25 } 26 }; 27 28 int n; 29 int par[MAX_N]; 30 long long ans; 31 long long a[MAX_N]; 32 vector<Edge> edge; 33 34 void read() 35 { 36 cin>>n; 37 for(int i=0;i<n;i++) 38 { 39 cin>>a[i]; 40 } 41 } 42 43 void build_graph() 44 { 45 for(int i=0;i<n;i++) 46 { 47 for(int j=0;j<i;j++) 48 { 49 edge.push_back(Edge(i,j,a[i]^a[j])); 50 } 51 } 52 } 53 54 void init_union_find() 55 { 56 for(int i=0;i<n;i++) 57 { 58 par[i]=i; 59 } 60 } 61 62 int find(int x) 63 { 64 return par[x]==x?x:par[x]=find(par[x]); 65 } 66 67 void unite(int x,int y) 68 { 69 int px=find(x); 70 int py=find(y); 71 if(px==py) return; 72 par[px]=py; 73 } 74 75 bool same(int x,int y) 76 { 77 return find(x)==find(y); 78 } 79 80 long long kruskal() 81 { 82 init_union_find(); 83 sort(edge.begin(),edge.end()); 84 int cnt=0; 85 long long res=0; 86 for(int i=0;i<edge.size();i++) 87 { 88 Edge temp=edge[i]; 89 if(!same(temp.sour,temp.dest)) 90 { 91 cnt++; 92 res+=temp.len; 93 unite(temp.sour,temp.dest); 94 } 95 } 96 return cnt==n-1?res:-1; 97 } 98 99 void solve() 100 { 101 build_graph(); 102 ans=kruskal(); 103 } 104 105 void print() 106 { 107 cout<<ans<<endl; 108 } 109 110 int main() 111 { 112 read(); 113 solve(); 114 print(); 115 }