病毒溯源

给定一棵树,树上有\(n\)个节点,编号从\(0\)到\(n-1\),请你输出从根节点开始的最长的一条链,且该链字典序最小

题解:\(dfs\)树的遍历 + 贪心

首先我们先找到入度为\(0\)的点作为根节点,为了保证我们找到第一条最长的链就是字典序最小的链,我们可以贪心的将每个节点的子节点进行排序,这样遍历树的时候优先会遍历节点编号小的点,那么我们得到的第一条最长的链就是字典序最小的点;

那么如何得到一条最长的链:

借助回溯搜索的思想,我们可以在刚进入该节点时,将该节点入队,然后在回溯到该节点时还原现场,将该节点出队,我们维护一条最长的链即可

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e4 + 10, M = 4e5 + 10; int n;
vector<int> g[N];
vector<int> ans;
vector<int> v;
int du[N]; void dfs(int u, int par)
{
v.push_back(u);
for (auto v : g[u])
{
if (v == par)
continue;
dfs(v, u);
}
if (v.size() > ans.size())
ans = v;
v.pop_back();
} void solve()
{
cin >> n;
for (int i = 0; i < n; ++i)
{
int k;
cin >> k;
vector<int> v;
for (int j = 1, u; j <= k; ++j)
{
cin >> u;
v.push_back(u);
du[u]++;
}
sort(all(v));
for (auto u : v)
{
g[i].push_back(u);
g[u].push_back(i);
}
}
int rt = 0;
for (int i = 0; i < n; ++i)
{
if (du[i] == 0)
{
rt = i;
break;
}
}
dfs(rt, -1);
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++)
cout << ans[i] << "\n "[i < ans.size() - 1];
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

清点代码库

首先假设两个功能模块如果接受同样的输入,总是给出同样的输出,则它们就是功能重复的;其次我们把每个模块的输出都简化为一个整数(在 int 范围内)。于是我们可以设计一系列输入,检查所有功能模块的对应输出,从而查出功能重复的代码。你的任务就是设计并实现这个简化问题的解决方案。

首先在第一行输出不同功能的个数 K。随后 K 行,每行给出具有这个功能的模块的个数,以及这个功能的对应输出。数字间以 1 个空格分隔,行首尾不得有多余空格。输出首先按模块个数非递增顺序,如果有并列,则按输出序列的递增序给出。

题解:\(map\) + 结构体自定义排序

注意:\(map\)能够对\(vector\)自动排序和映射,其他按照题意模拟即可

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10, M = 4e5 + 10; int n, m;
map<vector<int>, int> mp; struct node
{
int cnt;
vector<int> v;
bool operator<(const node &t) const
{
if (cnt != t.cnt)
return cnt > t.cnt;
else
{
for (int i = 0; i < v.size(); ++i)
{
if (v[i] != t.v[i])
return v[i] < t.v[i];
}
return true;
}
}
}; void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
vector<int> v;
for (int j = 1; j <= m; ++j)
{
int x;
cin >> x;
v.push_back(x);
}
mp[v]++;
}
vector<node> ans;
for (auto [x, y] : mp)
{
node t;
t.v = x;
t.cnt = y;
ans.push_back(t);
}
sort(all(ans));
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i].cnt << " ";
for (int j = 0; j < ans[i].v.size(); ++j)
cout << ans[i].v[j] << "\n "[j < ans[i].v.size() - 1];
}
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

还原文件

题解:\(dfs\)回溯搜索

从第一个折线角点开始搜索,设开始匹配的位置为\(p\),如果有一个纸条匹配成功,设匹配成功的纸条长度为\(d\),那么我们就从\(p+d-1\)的位置重新开始匹配,如果匹配失败我们回溯还原现场,注意已经被匹配的纸条不能参与匹配,直到匹配到最后一个折线角点为止

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10, M = 1e2 + 10; int n, m;
int a[N];
vector<int> g[M];
bool flag;
vector<int> ans;
bool vis[N]; void dfs(int p)
{
if (ans.size() == m)
{
for (int i = 0; i < ans.size(); ++i)
cout << ans[i] << "\n "[i < ans.size() - 1];
flag = true;
return;
}
if (flag)
return;
for (int i = 1; i <= m; ++i)
{
if (vis[i])
continue;
bool ok = true;
for (int j = 0; j < g[i].size(); ++j)
{
if (g[i][j] != a[p + j])
{
ok = false;
break;
}
}
if (ok)
{
vis[i] = true;
ans.push_back(i);
dfs(p + g[i].size() - 1);
if (flag)
return;
vis[i] = false;
ans.pop_back();
}
}
} void solve()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
cin >> m;
for (int i = 1; i <= m; ++i)
{
int k;
cin >> k;
for (int j = 1; j <= k; ++j)
{
int x;
cin >> x;
g[i].push_back(x);
}
}
dfs(1);
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

森森旅游

有\(n\)座城市和\(m\)条路,每个城市可以用\(1\)元现金换\(a_i\)的旅游金,我们每次经过一条路只能选择支付现金\(c\)元或旅游金\(d\)元,但不能混用;现在我们需要从\(1\)号城市前往城市\(n\),我们需要在途中的某个城市\(j\)将所有剩余现金全部换成旅游金,也就是说,在到城市\(j\)之前我们只能用现金支付,过了城市\(j\)之后我们只能用旅游金支付;

现在有\(q\)次询问,每次询问改变一个城市的汇率,询问你至少带多少现金能够从1号城市到n号城市,每次询问在前一次询问的基础上改变

题解:最短路\(dij\) + 反向建图 + \(multiset\)维护最小值 \(O(nlogn)\)

我们可以先跑一次\(dij\)求出城市1到其他城市的最少现金,然后反向建图,求出\(n\)号城市到其他城市的最少旅游金,这样对于任意可达一个城市\(k\)来说我们就知道在该城市换旅游金最终需要带多少现金

根据题意该题无法离线,所以我们考虑动态维护每个可达城市中在该城市换旅游金最终需要带现金的最小值,使用\(multiset/map\)维护即可

注意:只有城市\(1\)和城市\(n\)都可达的城市才需要维护,否则不计入答案

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10, M = 4e5 + 10; int n, m, q;
int a[N];
int dis1[N], dis2[N];
int vis[N]; struct node
{
int u, c, d;
};
vector<node> g[N], G[N]; void dij1(int st)
{
for (int i = 1; i <= n; ++i)
vis[i] = 0, dis1[i] = INF;
priority_queue<pii, vector<pii>, greater<pii>> q;
dis1[st] = 0;
q.push({dis1[st], st});
while (q.size())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = 1;
for (auto [v, c, d] : g[u])
{
if (dis1[v] > dis1[u] + c)
{
dis1[v] = dis1[u] + c;
q.push({dis1[v], v});
}
}
}
} void dij2(int st)
{
for (int i = 1; i <= n; ++i)
vis[i] = 0, dis2[i] = INF;
priority_queue<pii, vector<pii>, greater<pii>> q;
dis2[st] = 0;
q.push({dis2[st], st});
while (q.size())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = 1;
for (auto [v, c, d] : G[u])
{
if (dis2[v] > dis2[u] + d)
{
dis2[v] = dis2[u] + d;
q.push({dis2[v], v});
}
}
}
} multiset<int> st; void solve()
{
cin >> n >> m >> q;
for (int i = 1, u, v, c, d; i <= m; ++i)
{
cin >> u >> v >> c >> d;
if (v == u)
continue;
g[u].push_back({v, c, d});
G[v].push_back({u, c, d});
}
dij1(1);
dij2(n);
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i <= n; ++i)
if (dis1[i] != INF && dis2[i] != INF)
st.insert(dis1[i] + (int)(ceil(1.0 * dis2[i] / a[i])));
while (q--)
{
int x, val;
cin >> x >> val;
if (dis1[x] != INF && dis2[x] != INF)
{
auto it = st.lower_bound(dis1[x] + (int)(ceil(1.0 * dis2[x] / a[x])));
st.erase(it);
a[x] = val;
st.insert(dis1[x] + (int)(ceil(1.0 * dis2[x] / a[x])));
}
cout << *(st.begin()) << endl;
}
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

随机推荐

  1. 待补 重要思考:求给无向图定向使得其变为DAG的方案数

    今天比赛考到了,不会,丢了 100 分. rk2,380 -> rk15,280 别问为什么 T4 没过,因为不会 T2. 方法一 \(O(3^n)\) 令 \(f_S\) 为子集 \(S\) ...

  2. webpack高版本抽离css样式报错[已解决]

    全局安装的webpack版本是5.51.1,webpack-cli是4.9的版本; 本来想用 extract-text-webpack-plugin 的,但是报错了,查了一下文档 发现,已经不支持新版 ...

  3. Go runtime 调度器精讲(三):main goroutine 创建

    原创文章,欢迎转载,转载请注明出处,谢谢. 0. 前言 回顾下 上一讲 的内容.主线程 m0 蓄势待发,准备干活.g0 为 m0 提供了执行环境,P 和 m0 绑定,为 m0 提供活,也就是 goro ...

  4. JavaScript Library – Lit

    前言 我写过一篇关于 Lit 的文章,Material Design, Angular Material, MDC, MWC, Lit 的关系. 如今 material-web MWC 已经发布 1. ...

  5. ASP.NET Core – DateTime, DateTimeOffset, DateOnly, TimeOnly, TimeSpan, TimeZone, NodaTime 使用基础

    前言 心血来潮,这篇讲点基础的东西. 对日期和时区 timezone 不熟悉的读者,请先看这篇 Time Zone, Leap Year, Date Format, Epoch Time 时区, 闰年 ...

  6. Angular 18+ 高级教程 – 目录

    请按顺序阅读 关于本教程 初识 Angular Get Started Angular Compiler (AKA ngc) Quick View Dependency Injection 依赖注入  ...

  7. 十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)

    十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式) @ 目录 十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式) 1. Spring Boot 配置 M ...

  8. Servlet——Tomcat8以前解决中文乱码问题

    Request 请求参数中文乱码问题         // 1.解决乱码问题:POST,getReader() request.setCharacterEncoding("UTF-8&quo ...

  9. 3.flask 源码解析:路由

    目录 一.flask 源码解析:路由 1.1 构建路由规则 1.2 werkzeug 路由逻辑 1.3 flask 路由实现 1.4 match 实现 Flask 源码分析完整教程目录:https:/ ...

  10. 祝贺开源之夏 2023 KubeSphere 社区项目中选学生!

    日前,开源之夏 2023 所有中选结果已出炉,在此祝贺各位中选的同学! 活动简介 开源之夏是由中科院软件所"开源软件供应链点亮计划"发起并长期支持的一项暑期开源活动,旨在鼓励在校学 ...