方法一:直接建图暴搜
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
#define MX 10010
struct node{
int minX, ppl, cnt, ttl;
double ecnt, ettl;
bool operator<(const node&oth)const{
return this->ettl == oth.ettl ? this->minX < oth.minX : this->ettl > oth.ettl;
}
};
int main(){
int n;
cin >> n;
vector<int> list;
vector<vector<int>> a(MX);
vector<int> num(MX), sum(MX);
for (int i = 0; i < n;++i){
int x, y, z;
cin >> x >> y >> z;
list.push_back(x);
if(y!=-1){
a[x].push_back(y);
a[y].push_back(x);
}
if(z!=-1){
a[x].push_back(z);
a[z].push_back(x);
}
int m;
cin >> m;
for (int j = 0; j < m;++j){
int son;
cin >> son;
a[x].push_back(son);
a[son].push_back(x);
}
int k,val;
cin >> k>>val;
num[x] += k;
sum[x] += val;
}
vector<int> vis(MX);
int minX = MX, cnt = 0, ttl = 0,ppl=0;
function<void(int)> dfs = [&](int x)
{
vis[x] = 1;
ppl++;
cnt += num[x];
ttl += sum[x];
minX = min(minX, x);
for(auto v:a[x])
if(!vis[v])
dfs(v);
};
vector<node> ans;
for(auto x:list){
if(!vis[x]){
minX = MX, cnt = ttl = ppl=0;
dfs(x);
ans.emplace_back(node{minX,ppl,cnt, ttl,1.0*cnt/ppl,1.0*ttl/ppl});
}
}
sort(ans.begin(), ans.end());
cout << ans.size() << "\n";
for (int i = 0; i < ans.size();++i)
printf("%04d %d %.3f %.3f\n",ans[i].minX,ans[i].ppl,ans[i].ecnt,ans[i].ettl);
}
方法二:并查集
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
#include<unordered_set>
using namespace std;
#define MX 10010
struct node{
int minX, ppl, cnt, ttl;
double ecnt, ettl;
bool operator<(const node&oth)const{
return this->ettl == oth.ettl ? this->minX < oth.minX : this->ettl > oth.ettl;
}
};
int main(){
int n;
cin >> n;
unordered_set<int> set;
vector<int> a(MX);
vector<int> num(MX), sum(MX), ppl(MX);
for (int i = 0;i<MX;++i)
a[i] = i;
function<int(int)> find = [&](int x) -> int
{
return x == a[x] ? x : a[x] = find(a[x]);
};
function<void(int, int)> merge = [&](int x, int y)
{
x = find(x), y = find(y);
if(x<y)
a[y] = x;
else if(y<x)
a[x] = y;
};
for (int i = 0; i < n;++i){
int x, y, z;
cin >> x >> y >> z;
set.insert(x);
ppl[x] = 1;
if(y!=-1){
merge(x, y);
set.insert(y);
ppl[y] = 1;
}
if(z!=-1){
merge(x, z);
set.insert(z);
ppl[z] = 1;
}
int m;
cin >> m;
for (int j = 0; j < m;++j){
int son;
cin >> son;
merge(x, son);
set.insert(son);
ppl[son] = 1;
}
int k,val;
cin >> k>>val;
num[x] += k;
sum[x] += val;
}
vector<node> ans;
for(auto x:set){
int root = find(x);
if(x!=root){
num[root] += num[x];
sum[root] += sum[x];
ppl[root]++;
}
}
for(auto x:set){
int root = find(x);
if(x==root){
ans.emplace_back(node{x, ppl[x], num[x],sum[x],1.0 * num[x] / ppl[x], 1.0 * sum[x] / ppl[x]});
}
}
sort(ans.begin(), ans.end());
cout << ans.size() << "\n";
for (int i = 0; i < ans.size();++i)
printf("%04d %d %.3f %.3f\n",ans[i].minX,ans[i].ppl,ans[i].ecnt,ans[i].ettl);
}
效率对比:
dfs用vis数组剪枝,建图用邻接表;并查集也压缩了路径;避免暴力枚举,将结点收入集合;最后只对结果排序
多跑了几次,结果都差不多,并查集稍快1ms左右,总体来说两者差距不大
内存方面dfs建图开销大,而且递归层数更多,所以输并查集。
DFS:
并查集: