病毒溯源

给定一棵树,树上有\(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. 微信小程序--云开发支付闭环

    云开发支付流程闭环 extends 微信小程序--使用云开发完成支付闭环 在上述文章中,我们对支付结果的处理更多依赖于小程序端的操作 订单号存储在小程序端 支付结果采用小程序端定时触发器轮询 现在我对 ...

  2. BOOST库array使用 类似std库的vector

    BOOST库的array,  类似std库的vector. 下图所示书籍的下载地址,我的另一篇博客内有记载: https://www.cnblogs.com/happybirthdaytoyou/p/ ...

  3. Sql介绍 与 Sql基础查询

    Sql介绍 与 Sql基础查询 SQL SQL也称为结构化查询语言(Structure Query Language),是一种用于管理和操作关系型数据库的标准化计算机语言,SQL语言广泛应用于各种关系 ...

  4. 【赵渝强老师】Redis的慢查询日志

    Redis慢查询日志帮助开发和运维人员定位系统存在的慢操作.慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息(慢查询ID,发生时间戳,耗时,命令的详细信息 ...

  5. git 设置代理和取消代理

    1.设置代理 git config --global http.proxy "127.0.0.1:1080" 2.取消代理 git config --global --unset ...

  6. Proxy 与 Object.defineProperty对比?

    1. Proxy 可以直接监听对象而非属性:但是 ,object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历.Proxy ...

  7. Docker高阶篇(一)

    本篇章主要为工作实践过程中对高端应用的处理和把控 1.Docker复杂安装 mysql的主从复制 https://www.bilibili.com/video/BV1gr4y1U7CY?p=41&am ...

  8. 基于 KubeSphere 的应用容器化在智能网联汽车领域的实践

    公司简介 某国家级智能网联汽车研究中心成立于 2018 年,是担当产业发展咨询与建议.共性技术研发中心.创新成果转化的国家级创新平台,旨在提高我国在智能网联汽车及相关产业在全球价值链中的地位. 目前着 ...

  9. nvm安装使用教程

    一.简介 既然你来了,那就不用解释太多,只需要知道 nvm是一款nodejs版本管理工具,通过它可以让我们切换不同版本的 nodejs. 二.下载nvm 1.在安装nvm之前,你要先确定是否安装了no ...

  10. NES 模拟器中音画同步问题

    背景 模拟器是与游戏和播放器都有相似之处的系统.模拟器与游戏的相似之处,在于都需要一个采集输入--执行逻辑--然后按一定帧率(通常是 60 FPS)把画面显示出来的循环.但是模拟器又需要模拟音频设备, ...