题目大意
给出一棵树,问每一层各有多少个叶子结点。
方法一:bfs
#include<bits/stdc++.h>
using namespace std;
int n, m, k, mx, cnt[105], mp[105];
vector<int> v[105];
queue<int> q;
void bfs()
{
q.push(1);
while(!q.empty()){
int p = q.front();
q.pop();
if(v[p].size() == 0)
mp[cnt[p]]++;
for(int i = 0; i < v[p].size(); i++){
int to = v[p][i];
cnt[to] = cnt[p] + 1;
mx = max(mx, cnt[to]);
q.push(to);
}
}
}
int main()
{
cin >> n >> m;
for(int i = 0; i < m; i++){
int id, x;
cin >> id >> k;
for(int j = 0; j < k; j++){
cin >> x;
v[id].push_back(x);
}
}
bfs();
for(int i = 0; i <= mx; i++)
printf("%d%c", mp[i], i == mx ? '\n' : ' ');
return 0;
}
方法二:dfs
#include<bits/stdc++.h>
using namespace std;
int n, m, k, mx, mp[105];
vector<int> v[105];
void dfs(int id, int depth)
{
if(v[id].size() == 0){
mp[depth]++;
mx = max(mx, depth);
return ;
}
for(int i = 0; i < v[id].size(); i++)
dfs(v[id][i], depth + 1);
}
int main()
{
cin >> n >> m;
for(int i = 0; i < m; i++){
int id, x;
cin >> id >> k;
for(int j = 0; j < k; j++){
cin >> x;
v[id].push_back(x);
}
}
dfs(1, 0);
for(int i = 0; i <= mx; i++)
printf("%d%s", mp[i], i == mx ? "\n" : " ");
return 0;
}
题目大意
给出一个正整数 n,表示有 n 个结点,分别为 1 ~ n,并给出 n - 1 条边,问是否能构成一棵树,如果不能,则输出其连通分量的个数,如果能,则输出能构成最深的树的高度时,树的根结点。如果有多个,就按照从小到大的顺序输出。
分析
先用 dfs 来计算它连通分量的个数,若存在多个连通分量,就输出 Error: x components,如果只有一个,就取第一次深搜得到的深度最深的任意一个结点,再对其进行一次 dfs,两次搜索得到的结点的并集就是我们所求的结果了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
int n, m, mx, vis[maxn];
vector<int> v[maxn], f;
set<int> s;
void dfs(int x, int h)
{
if(h > mx){
f.clear();
f.push_back(x);
mx = h;
}
else if(h == mx)
f.push_back(x);
vis[x] = 1;
for(int i = 0; i < v[x].size(); i++){
if(!vis[v[x][i]])
dfs(v[x][i], h + 1);
}
}
int main()
{
cin >> n;
for(int i = 1; i < n; i++){
int a, b;
cin >> a >> b;
v[a].push_back(b);
v[b].push_back(a);
}
int root = 0, num = 0;
for(int i = 1; i <= n; i++){
if(!vis[i]){
dfs(i, 1);
if(i == 1){
if(f.size() != 0)
m = f[0];
for(int j = 0; j < f.size(); j++)
s.insert(f[j]);
}
num++;
}
}
if(num > 1){
printf("Error: %d components\n", num);
}
else{
f.clear();
mx = 0;
memset(vis, 0, sizeof(vis));
dfs(m, 1);
for(int i = 0; i < f.size(); i++)
s.insert(f[i]);
for(auto it : s)
printf("%d\n", it);
}
return 0;
}
题目大意
给定两个正整数 n, l,分别表示用户数量和最多转发层数,而用户 id 用 1 ~ n 表示,然后再给出每个用户关注的人的 id,求某个 id 发了微博后最多会有多少人转发。
分析
用 bfs 搜索在 l 层范围内的即可,但需要注意的是,每个用户只能转发一次,所以还需定义一个 vis 数组判断其是否入队过。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e3 + 10;
int n, l, m, uid, k, cnt, vis[maxn];
vector<int> v[maxn];
void bfs()
{
memset(vis, 0, sizeof(vis));
cnt = 0;
priority_queue<pii, vector<pii>, greater<pii> > q;
q.push({0, uid});
vis[uid] = 1;
while(!q.empty()){
pii p = q.top();
q.pop();
int m = p.second;
for(int i = 0; i < v[m].size(); i++){
int level = p.first + 1;
if(!vis[v[m][i]] && level <= l){
cnt++;
vis[v[m][i]] = 1;
q.push({level, v[m][i]});
}
}
}
}
int main()
{
cin >> n >> l;
for(int i = 1; i <= n; i++){
cin >> m;
for(int j = 1; j <= m; j++){
int x;
cin >> x;
v[x].push_back(i);
}
}
cin >> k;
for(int i = 1; i <= k; i++){
cin >> uid;
bfs();
cout << cnt << endl;
}
return 0;
}
1079 Total Sales of Supply Chain (25 分)
题目大意
给定一棵树,树根的价格为 p,从根结点开始,每往下一层,价格就上涨 r%,叶节点表示零售商,给出叶节点的货物量,求它们的价格之和。
方法一:bfs
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
int n, k, f[maxn], cnt[maxn], vis[maxn];
double p, r;
vector<int> v[maxn];
void bfs(int s)
{
memset(vis, 0, sizeof(vis));
cnt[s] = 0;
priority_queue<pii, vector<pii>, greater<pii> > q;
q.push({0, s});
while(!q.empty()){
pii p = q.top();
q.pop();
int m = p.second;
if(vis[m])
continue;
vis[m] = 1;
for(int i = 0; i < v[m].size(); i++){
int tt = v[m][i];
cnt[tt] = cnt[m] + 1;
q.push({cnt[tt], tt});
}
}
}
int main()
{
cin >> n >> p >> r;
for(int i = 0; i < n; i++){
cin >> k;
for(int j = 0; j < k; j++){
int x;
cin >> x;
v[i].push_back(x);
}
if(k == 0){
int x;
cin >> x;
f[i] = x;
}
}
bfs(0);
double sum = 0;
for(int i = 0; i < n; i++)
if(f[i] != 0)
sum += p * pow(1 + r / 100, cnt[i]) * f[i];
printf("%.1lf\n", sum);
return 0;
}
方法二:dfs
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
int n, k, f[maxn], cnt[maxn], vis[maxn];
double p, r;
vector<int> v[maxn];
void dfs(int s, int level)
{
if(v[s].size() == 0){
cnt[s] = level;
return ;
}
for(int i = 0; i < v[s].size(); i++)
dfs(v[s][i], level + 1);
}
int main()
{
cin >> n >> p >> r;
for(int i = 0; i < n; i++){
cin >> k;
for(int j = 0; j < k; j++){
int x;
cin >> x;
v[i].push_back(x);
}
if(k == 0){
int x;
cin >> x;
f[i] = x;
}
}
dfs(0, 0);
double sum = 0;
for(int i = 0; i < n; i++)
if(f[i] != 0)
sum += p * pow(1 + r / 100, cnt[i]) * f[i];
printf("%.1lf\n", sum);
return 0;
}
题目大意
给定一个三维数组,0 表示正常,1 表示有肿瘤,肿瘤块的大小大于等于 t 才算是肿瘤,计算所有满足肿瘤块的大小。
#include<bits/stdc++.h>
using namespace std;
int m, n, l, t, f[1300][130][70], vis[1300][130][70];
int dx[6] = {1, -1, 0, 0, 0, 0};
int dy[6] = {0, 0, 1, -1, 0, 0};
int dz[6] = {0, 0, 0, 0, 1, -1};
struct node{
int x, y, z;
};
bool judge(int x, int y, int z)
{
if(x < 0 || x >= m || y < 0 || y >= n || z < 0 || z >= l)
return false;
if(f[x][y][z] == 0 || vis[x][y][z])
return false;
return true;
}
int bfs(int x, int y, int z)
{
queue<node> q;
q.push({x, y, z});
vis[x][y][z] = 1;
int cnt = 0;
while(!q.empty()){
node p = q.front();
q.pop();
cnt++;
for(int i = 0; i < 6; i++){
int xx = p.x + dx[i];
int yy = p.y + dy[i];
int zz = p.z + dz[i];
if(judge(xx, yy, zz)){
q.push({xx, yy, zz});
vis[xx][yy][zz] = 1;
}
}
}
if(cnt >= t)
return cnt;
else
return 0;
}
int main()
{
cin >> m >> n >> l >> t;
for(int i = 0; i < l; i++){
for(int j = 0; j < m; j++){
for(int k = 0; k < n; k++){
cin >> f[j][k][i];
}
}
}
int sum = 0;
for(int i = 0; i < l; i++){
for(int j = 0; j < m; j++){
for(int k = 0; k < n; k++){
if(f[j][k][i] == 1 && !vis[j][k][i]){
sum += bfs(j, k, i);
}
}
}
}
cout << sum << endl;
return 0;
}
1094 The Largest Generation (25 分)
题目大意
给定一棵树,求结点个数最多的一层,输出其结点个数及层号。
方法一:bfs
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
int n, m, k, id, mx, mxLevel, cnt[105];
vector<int> v[105];
map<int, int> mp;
void bfs(int s)
{
queue<int> q;
q.push(s);
cnt[s] = 1;
while(!q.empty()){
int p = q.front();
q.pop();
mp[cnt[p]]++;
for(int i = 0; i < v[p].size(); i++){
int tt = v[p][i];
cnt[tt] = cnt[p] + 1;
q.push(tt);
}
}
return ;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i++){
cin >> id >> k;
for(int i = 1; i <= k; i++){
int x;
cin >> x;
v[id].push_back(x);
}
}
bfs(1);
int ans = 0, ansLevel = 1;
for(int i = 1; i <= 100; i++){
if(mp[i] > ans){
ans = mp[i];
ansLevel = i;
}
}
cout << ans << " " << ansLevel << endl;
return 0;
}
方法二:dfs
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
int n, m, k, id, mx, mxLevel;
vector<int> v[105];
map<int, int> mp;
void dfs(int s, int level)
{
mp[level]++;
for(int i = 0; i < v[s].size(); i++){
dfs(v[s][i], level + 1);
}
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i++){
cin >> id >> k;
for(int i = 1; i <= k; i++){
int x;
cin >> x;
v[id].push_back(x);
}
}
dfs(1, 1);
int ans = 0, ansLevel = 1;
for(int i = 1; i <= 100; i++){
if(mp[i] > ans){
ans = mp[i];
ansLevel = i;
}
}
cout << ans << " " << ansLevel << endl;
return 0;
}
1103 Integer Factorization (30 分)
题目大意
给定正整数 n,k,p,问是否存在 k 个数,每个数的 p 次方之和为 n,若存在多组,则输出因子总和最大的一组。
#include<bits/stdc++.h>
using namespace std;
int n, k, p, mx, a[405], ans[405];
void dfs(int x, int num, int sum, int fac)
{
if(x > n || num > k)
return ;
if(x == n && num == k){
if(mx < sum){
for(int i = 0; i < num; i++)
ans[i] = a[i];
mx = sum;
}
return ;
}
for(int i = fac; i >= 1; i--){
a[num] = i;
dfs(x + pow(i, p), num + 1, sum + i, i);
}
}
int main()
{
cin >> n >> k >> p;
dfs(0, 0, 0, sqrt(n));
if(mx != 0){
sort(ans, ans + k);
printf("%d = %d^%d", n, ans[k-1], p);
for(int i = k-2; i >= 0; i--)
printf(" + %d^%d", ans[i], p);
printf("\n");
}
else
printf("Impossible\n");
return 0;
}
1106 Lowest Price in Supply Chain (25 分)
题目大意
给定一棵树,树根处的价格为 p,从根结点开始,每往下一层,该层货物的价格就会在其父亲结点的价格上增加 r%。在叶子结点处能获得的最低价格,及能提供最低价格的叶子结点数。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, k, mn, num, cnt[maxn];
double p, r;
vector<int> f[maxn];
void dfs(int s)
{
if(f[s].size() == 0){
if(mn > cnt[s]){
mn = cnt[s];
num = 1;
}
else if(mn == cnt[s])
num++;
}
for(int i = 0; i < f[s].size(); i++){
cnt[f[s][i]] = cnt[s] + 1;
dfs(f[s][i]);
}
}
int main()
{
cin >> n >> p >> r;
for(int i = 0; i < n; i++){
cin >> k;
for(int j = 0; j < k; j++){
int x;
cin >> x;
f[i].push_back(x);
}
}
mn = 0x3f3f3f3f;
num = 0;
dfs(0);
printf("%.4lf %d\n", p * pow(1 + r/100, mn), num);
return 0;
}
1127 ZigZagging on a Tree (30 分)
题目大意
给定一棵树的中序和后序遍历结果,求它的 Z 型层序遍历,即奇数层从左往右遍历,偶数层从右往左遍历。
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> in, post;
struct node{
int a, b, c;
};
bool cmp(node x, node y){
if(x.b == y.b){
if(x.b % 2)
return x.c > y.c;
else
return x.c < y.c;
}
return x.b < y.b;
}
vector<node> ans;
void dfs(int root, int l, int r, int index, int depth)
{
if(l > r)
return ;
int i = l;
while(in[i] != post[root] && i <= r) i++;
ans.push_back({post[root], depth, index});
dfs(root - (r - i + 1), l, i - 1, index * 2 + 1, depth + 1);
dfs(root - 1, i + 1, r, index * 2 + 2, depth + 1);
}
int main()
{
cin >> n;
in.resize(n + 1);
post.resize(n + 1);
for(int i = 1; i <= n; i++)
cin >> in[i];
for(int i = 1; i <= n; i++)
cin >> post[i];
dfs(n, 1, n, 1, 1);
sort(ans.begin(), ans.end(), cmp);
for(int i = 0; i < ans.size(); i++)
printf("%d%s", ans[i].a, i == ans.size() - 1 ? "\n" : " ");
return 0;
}
题目大意
给定一棵二叉树,输出它的中缀表达式,并加上括号表示运算的优先级。
#include<bits/stdc++.h>
using namespace std;
int n, root = 1;
struct node{
string val;
int l, r;
};
vector<node> v;
string dfs(int index)
{
if(index == -1) return "";
if(v[index].r != -1){
v[index].val = dfs(v[index].l) + v[index].val + dfs(v[index].r);
if(index != root) v[index].val = '(' + v[index].val + ')';
}
return v[index].val;
}
int main()
{
cin >> n;
v.resize(n + 1);
vector<bool> vis(n + 1, false);
for(int i = 1; i <= n; i++){
cin >> v[i].val >> v[i].l >> v[i].r;
if(v[i].l != -1) vis[v[i].l] = true;
if(v[i].r != -1) vis[v[i].r] = true;
}
while(vis[root] == true) root++;
cout << dfs(root) << endl;
return 0;
}
题目大意
给定起点和终点,要求你给出一条路线,使得中途停站最少,如果停站数量一样多,就选择换乘线路次数最少的路线。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, m, k, pre, minCnt, minTransfer, st, ed;
vector<int> v[maxn], path, tempPath;
unordered_map<int, int> line;
int vis[maxn];
int func(vector<int> a)
{
int num = 0, preLine = line[a[0] * 10000 + a[1]];
for(int i = 1; i < a.size(); i++){
if(line[a[i] * 10000 + a[i + 1]] != preLine)
num++;
preLine = line[a[i] * 10000 + a[i + 1]];
}
return num;
}
void dfs(int node, int cnt)
{
if(node == ed && (cnt < minCnt || (func(tempPath) < minTransfer && cnt == minCnt))){
minCnt = cnt;
minTransfer = func(tempPath);
path = tempPath;
}
if(node == ed) return ;
for(int i = 0; i < v[node].size(); i++){
if(!vis[v[node][i]]){
vis[v[node][i]] = 1;
tempPath.push_back(v[node][i]);
dfs(v[node][i], cnt + 1);
vis[v[node][i]] = 0;
tempPath.pop_back();
}
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++){
cin >> m >> pre;
for(int j = 1; j < m; j++){
int x;
cin >> x;
v[pre].push_back(x);
v[x].push_back(pre);
line[pre * 10000 + x] = line[x * 10000 + pre] = i;
pre = x;
}
}
cin >> k;
while(k--){
cin >> st >> ed;
minCnt = 99999, minTransfer = 99999;
memset(vis, 0, sizeof(vis));
tempPath.clear();
tempPath.push_back(st);
path.clear();
vis[st] = 1;
dfs(st, 0);
vis[st] = 0;
cout << minCnt << endl;
int preLine = line[path[0] * 10000 + path[1]], preNode = path[0];
for(int i = 1; i < path.size(); i++){
if(line[path[i] * 10000 + path[i + 1]] != preLine){
printf("Take Line#%d from %04d to %04d.\n", preLine, preNode, path[i]);
preLine = line[path[i] * 10000 + path[i + 1]];
preNode = path[i];
}
}
}
return 0;
}