1. 程式人生 > >BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成樹

BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成樹

sort -1 iostream php ref log ring nbsp 題目

題目鏈接: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 }

BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成樹