家庭房产 并查集和DFS两种————详细!!!

比较开心 虽然做的时间比较长
这是我第二个做的这种类型的并查集 上一个是 部落

题解(之前的)

难的地方是怎么存数据
单独开一个数组 以每个家族的族长为下标来存数据
在输入的时候的把一个部落的都连在一起
在把人们的祖先用set过一遍去重 set的大小就是部落的个数

注释很详细

DFS(老师又贴了他的代码给我看 我敲了一遍)

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <set>
#include <vector>
#include <map>
using namespace std;
struct node
{
	int id, pcnt, rcnt, acnt;
};
//id是int node是id里的信息
map<int, node> info;
//把所有人的id记录 方便下面遍历 所有人
set<int> people;
//放最后每个部落的总答案
vector<node> ans;
//防止重复访问
vector<bool> dp(10000);
//邻接表存图
vector<int> g[10000];
//存图+存人
void addEdge(int x, int y)
{
	g[x].push_back(y);
	g[y].push_back(x);
	people.insert(y);
}
void dfs(int x)
{
	//下面循环一次就回把那个人所有的家人访问一遍
	auto &i = ans.back();
	//找的时候答案就直接放ans里了
	i.id = min(i.id, x);
	//总人数加
	++i.pcnt;
	//房子和面积
	i.acnt += info[x].acnt;
	i.rcnt += info[x].rcnt;
	dp[x] = 1;
	//在通过这个人x 来访问家人
	for (auto e : g[x])
	{
		if (!dp[e])
			dfs(e);
	}
}
int main()
{
	int N;
	cin >> N;
	for (int i = 0; i < N; ++i)
	{
		int x, px, mx, k;
		cin >> x >> px >> mx >> k;
		people.insert(x);
		//把他们都连在一家之主身上
		//妈妈和爸爸就没有必要再相连了
		//因为他们都连着儿子 就回走通的
		if (px != -1)
		{
			addEdge(x, px);
		}
		if (mx != -1)
		{
			addEdge(x, mx);
		}
		while (k--)
		{
			int cd;
			cin >> cd;
			addEdge(x, cd);
		}
		int r, a;
		cin >> r >> a;
		//map 通过id索引 id的内容
		//而有的人根本没加入map里面
		//不过没事 不加的就是0 不影响
		info[x] = {x, 1, r, a};
	}
	//遍历所有人
	for (auto e : people)
	{
		if (!dp[e])
		{
			//因为要找最小的id 所以一开始给ans一开大的数
			ans.push_back({9999, 0, 0, 0});
			dfs(e);
		}
	}
	//ans的个数就是部落数了
	cout << ans.size() << endl;
	//排序规则
	auto cmp = [](node e1, node e2) {
		double x = e1.acnt * 1.0 / e1.pcnt;
		double y = e2.acnt * 1.0 / e2.pcnt;
		return x == y ? e1.id < e2.id : x > y;
	};
	sort(ans.begin(), ans.end(), cmp);
	//这几个函数我也写了博客
	//在我博客里搜索 输入即可
	for (auto i : ans)
	{
		cout << setw(4) << setfill('0') << i.id << ' ';
		cout << i.pcnt << ' ';
		cout << fixed << setprecision(3) << i.rcnt * 1.0 / i.pcnt << ' ';
		cout << i.acnt * 1.0 / i.pcnt << endl;
	}

	return 0;
}

并查集

#include <iostream>
#include <numeric>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
struct node
{
    int id, t;
    double home, s;
} ans[10005];
//ans主要放home和s
//dp里放祖先
vector<int> dp(10005);
int find(int x)
{
    return dp[x] == x ? x : dp[x] = find(dp[x]);
}
//并
void uni(int x, int y)
{
    //看是不是去世了
    if (y == -1 || x == -1)
        return;
    //看y 之前有没有改过祖先
    if (dp[y] == -1)
        dp[y] = y;
    int a = find(x);
    int b = find(y);
    if (a != b)
    {
        dp[b] = a;
    }
}
int main()
{
    int n;
    cin >> n;
    //默认为-1
    fill(dp.begin(), dp.end(), -1);
    //把全部的人放到tt里
    //方便下面找祖先 用set主要是去重复的人
    set<int> tt;
    int m;
    for (int i = 0; i < n; ++i)
    {
        int id;
        cin >> id;
        // pro.push_back(id);
        tt.insert(id);
        //看是不是之前没遇到过
        //没有的话就弄成自己
        if (dp[id] == -1)
            dp[id] = id;
        for (int i = 0; i < 2; i++)
        {
            int id_;
            cin >> id_;
            if (id_ == -1)
                continue;
            //可以看一下uni里 把id作为祖先
            uni(id, id_);
            tt.insert(id_);
            // pro.push_back(id_);
        }
        int n1, n2, x;
        cin >> n1;
        for (int i = 0; i < n1; ++i)
        {
            cin >> x;
            // pro.push_back(x);
            tt.insert(x);
            uni(id, x);
        }
        cin >> n2;
        //本来我想的是把一个家族的祖先当下标
        //把数据存里面 不过发生了一些未知错误
        //我懒得找了(找不到啊)
        //就在第99行加了两个变量
        //因为他们的祖先是不变的 所以:...看下面就知道了
        ans[find(id)].home += (double)n2;
        cin >> x;
        ans[find(id)].s += (double)x;
    }

    //现在就把家族分好了 主要的工作就是找他们家族对应的id和数据

    //home里放的是祖先
    //因为祖先的个数是有限的
    set<int> home;
    //home里放的是各大家族的祖先 为的是对应数据
    for (auto e : tt)
    {
        home.insert(find(e));
    }
    //home的个数就是家族的个数
    cout << home.size() << endl;
    //an就是答案了
    vector<node> an;
    //下面就是找之前存的 面积和房子数
    for (auto e : home)
    {
        double home = 0, st = 0;
        int mint = 9999999;
        set<int> t;
        //t是找个数
        for (auto s : tt)
        {
            if (find(s) == e)
            {
                home += ans[s].home;
                st += ans[s].s;
                //找最小的id
                mint = min(mint, s);
                t.insert(s);
            }
        }
        home /= t.size();
        st /= t.size();
        an.push_back({mint, (int)t.size(), home, st});
    }
    sort(an.begin(), an.end(), [](auto e1, auto e2) { if(e1.s==e2.s) return e1.id<e2.id;return e1.s>e2.s; });
    for (auto e : an)
    {
        printf("%04d %d %.3f %.3f\n", e.id, e.t, e.home, e.s);
    }

    return 0;
}
发布了106 篇原创文章 · 获赞 25 · 访问量 7233

猜你喜欢

转载自blog.csdn.net/weixin_45653525/article/details/104161091
今日推荐