据说今年的天梯赛比以往简单,咱也不知道,没啥感觉,第一次参加天梯赛,所以并不晓得以往正式赛难度如何,反正我这次是失败告终了,难受啊,本来拿个个人三等应该是势在必得的,遇到病毒之后惨了,强行卡了一个多小时,斩获0分。哎,,不说了,都是辛酸泪啊。。。菜鸡流泪。
那就先来解决病毒溯源这个毒瘤吧。
看清题目,看清题目,看清题目。。。
(ps:如果长链不唯一,输出最小序列)
补题传送门
解题思路:
就是直接暴力的思路。病毒源只有一个,可以记录顶点的度数来寻找病毒源。找到病毒源之后,用 B F S BFS BFS 求一个单源最长路即可。用 f a [ i ] fa[i] fa[i]数组来记录第 i i i 个节点的父亲节点。根据父亲节点与子节点之间的关系,逆向寻找路径,用二维 v e c t o r vector vector 数组记录所有可行方案,再来个排序输出第一个即为最终答案。
C++ AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<int> v[10010];
int d[10010], dist[10010], fa[10010];
vector<vector<int> > res;
int ans, root;
bool vis[10010];
void bfs()
{
queue<int> q;
q.push(root);
dist[root] = 1;
while (q.size())
{
int u = q.front();q.pop();
for (int i = 0;i < v[u].size();i++)
{
int j = v[u][i];
if (dist[j] < dist[u] + 1)
{
dist[j] = dist[u] + 1;
fa[j] = u;
q.push(j);
}
}
}
}
bool cmp(vector<int> x, vector<int> y)
{
for (int i = 0;i < x.size();i++)
{
if (x[i] != y[i]) return x[i] < y[i];
}
}
int main()
{
int n; scanf("%d", &n);
for (int i = 0;i < n;i++)
{
int k; scanf("%d", &k);
d[i]++;
for (int j = 0;j < k;j++)
{
int x; scanf("%d", &x);
v[i].push_back(x);
d[x]++;
}
}
while (d[root] != 1) root++;
bfs();
fa[root] = root;
int pos;
for (int i = 0;i < n;i++)
{
ans = max(ans, dist[i]);
}
printf("%d\n", ans);
for (int i = 0;i < n;i++)
{
if (dist[i] == ans)
{
vector<int> tmp;
int rt = i;
while (fa[rt] != rt)
{
tmp.push_back(rt);
rt = fa[rt];
}
tmp.push_back(root);
reverse(tmp.begin(), tmp.end());
res.push_back(tmp);
}
}
sort(res.begin(), res.end(), cmp);
for (int i = 0;i < res[0].size();i++)
{
printf("%d", res[0][i]);
if (i < res[0].size() - 1) printf(" ");
}
return 0;
}
补题传送门
这个题是个简单的队列与栈的操作,不做过多解释,直接放上我的代码吧。
C++ AC代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
queue<char> q[110];
int op[100010];
char st[110];//框
int s;
int main()
{
int N, M, S; cin >> N >> M >> S;
for (int i = 1;i <= N;i++)
{
string str; cin >> str;
for (int j = 0;j < str.size();j++) q[i].push(str[j]);
}
M = 0;
while (1)
{
int x; cin >> x;
if (x == -1) break;
op[++M] = x;
}
vector<char> res;//传送带上物品
for (int i = 1;i <= M;i++)
{
int k = op[i];
if (k == 0)
{
if (s) res.push_back(st[s--]);
}
else {
if (q[k].empty()) continue;
if (s < S){
st[++s] = q[k].front();q[k].pop();
}
else {
res.push_back(st[s--]);
st[++s] = q[k].front();q[k].pop();
}
}
}
for (int i = 0;i < res.size();i++)
{
cout << res[i];
}
return 0;
}
补题传送门
解题思路:
这个题还真就长见识了,两个 v e c t o r vector vector 容器可以直接比较大小,比较规则是从前往后遍历每一个元素,返回第一个不相等的元素的比较结果。可以放进 s e t set set 中,也可以放进 m a p map map 中。这样的话,就很好操做了。一开始我使用 m a p map map 记录出现的次数,利用 s e t set set 去重,但可能是卡 m a p map map 了,只能得到 21 21 21 分。得到满分的做法是先排序,相同的就会在相邻的位置,从前往后遍历,记录出现次数,用结构体存储可以比较方便的实现排序及计数。
注意:这个题会卡 c i n cin cin 和 c o u t cout cout.
C++ Score 25:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<vector<int> > v;
struct node {
int sum;
vector<int> tmp;
}st[10010];
int s;
bool cmp(node x, node y)
{
if (x.sum != y.sum) return x.sum > y.sum;
else return x.tmp < y.tmp;
}
int main()
{
int n, m; scanf("%d%d", &n, &m);
for (int i = 0;i < n;i++)
{
vector<int> tmp;
for (int j = 0;j < m;j++)
{
int x; scanf("%d", &x);
tmp.push_back(x);
}
v.push_back(tmp);
}
sort(v.begin(), v.end());
st[++s] = {
1,v[0] };
for (int i = 1;i < n;i++)
{
if (v[i] != v[i - 1])
{
st[++s] = {
1,v[i] };
}
else st[s].sum++;
}
sort(st + 1, st + s + 1, cmp);
printf("%d\n", s);
for (int i = 1;i <= s;i++)
{
printf("%d", st[i].sum);
for (int j = 0;j < st[i].tmp.size();j++)
{
printf(" %d", st[i].tmp[j]);
}
if (i < s) printf("\n");
}
return 0;
}
C++ Score 21:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<int> v[10010];
map<vector<int>, int> mp;
set<vector<int> > s;
bool cmp(vector<int> x, vector<int> y)
{
if (mp[x] != mp[y]) return mp[x] > mp[y];
return x < y;
}
int main()
{
int n, m; scanf("%d%d",&n,&m);
for (int i = 0;i < n;i++)
{
for (int j = 0;j < m;j++)
{
int x; scanf("%d",&x);
v[i].push_back(x);
}
mp[v[i]]++;
s.insert(v[i]);
}
vector<vector<int> > res;
for (auto item : s) {
res.push_back(item);
}
sort(res.begin(), res.end(), cmp);
/*for (int i = 0;i < res.size();i++)
{
for (int j = 0;j < res[i].size();j++)
{
cout << res[i][j] << " ";
}
cout << endl;
}*/
printf("%d\n",res.size());
for (int i = 0;i < res.size();i++)
{
printf("%d",mp[res[i]]);
for (int j = 0;j < res[i].size();j++)
{
printf(" %d",res[i][j]);
}
if (i < res.size() - 1) printf("\n");
}
return 0;
}
补题传送门
阅读理解题,按照题目描述模拟就OK,so easy 呀。无语了,当时就应该先开这个题的,策略问题,当时看到题目描述有点长,就习惯性的略古了,直接留到了后面,然而到后面之后根本没心思冷静下来读题,难受。
C++ Score 25:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 100010;
vector<int> v[N];
int mark[N];
int main()
{
int n, m; scanf("%d%d", &n, &m);
for (int i = 1;i <= n;i++)
{
int k; scanf("%d", &k);
v[i].push_back(0);
for (int j = 1;j <= k;j++)
{
int x;scanf("%d", &x);
v[i].push_back(x);
}
}
int now = 1;
while (m--)
{
int op, x; scanf("%d%d", &op, &x);
if (op == 1)
{
mark[x] = now;
printf("%d\n",mark[x]);
}
else if(op == 0){
now = v[now][x];
}
else if (op == 2)
{
now = mark[x];
}
}
printf("%d", now);
return 0;
}
L2补题完毕。
L3明天继续。。。