[ANOJ]1024宇宙树[dfs-并查集]

1. 原题:https://logn.me/problem/1024

2. 思路

题意: 树的遍历问题。
该题可以用并查集写,
我觉得麻烦,直接用的dfs来处理。
注意,类型可能为0。
已AC

3. 源码:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;

int N, M, cnt = 0; //**cnt记录树的个数
string sum;//**记录每棵树的类型
const int Max = 10002; //**最大结点数
vector<int> G[Max];//**树的邻接表表示
vector<string> res;//**存储所有树类型
int wt[Max] = { 0 }, vis[Max] = { 0 };//wt为初始类型

void dfs(int x, string &st);//递归获取树类型
void myadd(string b);//大整数加法

int main()
{
	//freopen("in.txt", "r", stdin);
	scanf("%d %d", &N, &M);
	for (int i = 0; i < N; i++)
	{
		scanf("%d", &wt[i]);
	}
	int ca, cb;
	for (int i = 0; i < M; i++)
	{
		scanf("%d %d", &ca, &cb);
		G[ca].push_back(cb);
	}

	for (int i = 0; i < N; i++)
	{
		if (vis[i] == 0) //访问未访问过的,这里已经默认从编号小的开始了
		{
			vis[i] = 1;
			string st;
			sum = "";
			cnt++;
			st.push_back(wt[i] + '0');
			dfs(i, st);
			res.push_back(sum);
		}
	}
	cout << cnt << endl;
	for (int i = 0; i < res.size(); i++)
	{
		if (i != 0)
			cout << " ";
		if (res[i] != "") //这里可能是空,要输出0
			cout << res[i];
		else
			cout << 0;
	}

	return 0;
}

void dfs(int x, string &st)//递归获取树类型
{
	if (G[x].size() < 1)//边界
	{
		myadd(st);
		return;
	}

	for (int w = 0; w < G[x].size(); w++)
	{
		int v = G[x][w];
		vis[v] = 1;
		st.push_back(wt[v] + '0');
		dfs(v, st);
		st.pop_back();
	}
	return;
}

void myadd(string b)//大整数加法
{
	while (1) //**去除前导0
	{
		if (b[0] == '0')
			b.erase(0, 1);
		else
			break;
	}

	string c(sum);
	reverse(c.begin(), c.end());//反转过来便于计算
	reverse(b.begin(), b.end());
	
	int len = min(c.size(), b.size());
	int carry = 0;//记录进位
	sum = "";
	for (int i = 0; i < len; i++)
	{
		int bg = b[i] - '0' + c[i] - '0' + carry;
		sum.push_back(bg % 10 + '0');
		carry = bg / 10;
	}
	for (int i = len; i < b.size(); i++)//这两个循环只会执行一个,
	{
		int bg = b[i] - '0' + carry;
		sum.push_back(bg % 10 + '0');
		carry = bg / 10;
	}
	for (int i = len; i < c.size(); i++)
	{
		int bg = c[i] - '0' + carry;
		sum.push_back(bg % 10 + '0');
		carry = bg / 10;
	}
	if (carry > 0)
		sum.push_back('1');
	reverse(sum.begin(), sum.end());
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值