Codeforces Round #743 (Div. 2)简训

Codeforces Round #743 (Div. 2)简训

导语

日常

涉及的知识点

贪心,思维,搜索,拓扑

链接:Codeforces Round #743 (Div. 2)

题目

A Countdown

题目大意:略

思路:直接把每一位交换到最后一位即可,特判最后一位是否为0,如果不为0就先把最后一位清0

代码

#include <bits/stdc++.h>
using namespace std;
int t,n,a[121];
int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        int sum=0,ans=0;
        for(int i=1; i<=n; i++) {
            scanf("%1d",&a[i]);
            sum+=a[i];
            if(a[i])ans++;
        }
        if(a[n])sum+=ans-1;
        else sum+=ans;
        printf("%d\n",sum);
    }
    return 0;
}

B Swaps

题目大意:给出一个数n,两个序列a和b,a是1-2n内所有的奇数,b是所有的偶数,现在定义一种操作如下:选择一个序列,交换第i项和第i+1项的位置,现在要求使用最少的操作次数使得a序列的字典序小于b的字典序,输出最少的操作次数

思路:a和b的数字各不相同,所以满足第一位即可,贪心的去考虑,对于a序列,如果把a[i]移动到第一位,那么就需要i-1次操作,之后找到b序列中首个数值大于a[i]的值移动到b[1]即可,假设这个数的位置为j,那么操作次数便是i+j-2,那么直接遍历原数组,计算出每个数移动到第一位的操作次数,随后对每个奇数计算出最优的偶数,选取最优解即可

代码

#include <bits/stdc++.h>
using namespace std;
int t,n,mp[212121];
const int inf=0x3f3f3f3f;
int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        int res=0,ans=0;
        for(int j=0; j<2; j++)//记录位置
            for(int i=0; i<n; i++) {
                int x;
                scanf("%d",&x);
                mp[x]=i;
            }
        ans=res=inf;//初始化
        for(int i=2*n; i>=1; i--)
            if(i&1)ans=min(ans,mp[i]+res);//如果是奇数
            else res=min(res,mp[i]);//更新首个大于当前奇数的最优偶数位置
        printf("%d\n",ans);
    }
    return 0;
}

C Book

题目大意:一本书,有n个章节,章节之间的阅读有拓扑关系,每次阅读遍历从1开始遍历n个章节,询问是否能读完全部章节,输出次数或-1

思路:是一个有偏向的拓扑排序,需要优先遍历编号小且入度为0的节点,在遍历过程中,如果下一个节点编号比当前节点大,代表在这次阅读过程中下一个节点可以被阅读,否则就需要增加阅读次数,以这个策略BFS图,获得最大的阅读次数,每次对能访问到的点需要减去其相邻点的入度,具体看代码

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int t,n,head[maxn],in[maxn],cnt;
typedef pair<int,int>pr;
const int inf=0x3f3f3f3f;
struct node {
    int next,to;
} e[maxn];
void Add(int from,int to) {//链式前向星建图
    e[++cnt].next=head[from];
    e[cnt].to=to;
    head[from]=cnt;
    in[to]++;
}
priority_queue<pr,vector<pr>,greater<pr>>q;
int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        int ans=0,res=0;
        for(int i=1; i<=n; i++) {//建有向图
            int k;
            scanf("%d",&k);
            while(k--) {
                int x;
                scanf("%d",&x);
                Add(x,i);
            }
        }
        for(int i=1; i<=n; i++)
            if(in[i]==0)q.push({1,i});
        while(!q.empty()) {
            auto u=q.top();
            q.pop();
            ans=u.first,res++;
            for(int i=head[u.second]; i; i=e[i].next) {
                int v=e[i].to;
                in[v]--;
                if(!in[v]) {
                    if(v<u.second)q.push({u.first+1,v});
                    else q.push({u.first,v});
                }
            }
        }
        if(res==n)printf("%d\n",ans);
        else printf("-1\n");
        memset(in,0,sizeof(int)*(n+1));
        memset(head,0,sizeof(int)*(n+1));
        while(!q.empty())q.pop();
        cnt=0;
    }
    return 0;
}

另一种实现

#include <iostream>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 2e5 + 7;

int head[maxn], nxt[maxn], ver[maxn];
int tot;
int n;
int in[maxn], dep[maxn];

void init(){
    memset(head, 0, sizeof (head));
    memset(in, 0, sizeof (in));
    memset(dep, 0, sizeof(dep));
    tot = 0;
}

void adde(int u, int v){
    ++tot; ver[tot] = v; nxt[tot] = head[u]; head[u] = tot;
}

int topsort(){
    queue <int> q;
    for (int i=1; i<=n; i++)
        if (!in[i]) q.push(i), dep[i] = 1;
    int ans = 0;
    while (!q.empty()){
        int h = q.front(); q.pop();
        ans = max(ans, dep[h]);
        for (int i=head[h]; i; i=nxt[i]){
            int v = ver[i];
            if (v < h) dep[v] = max(dep[h]+1, dep[v]);
            else dep[v] = max(dep[h], dep[v]);
            in[v] --;
            if (!in[v]) q.push(v);
        }
    }
    for (int i=1; i<=n; i++){
        if (in[i]){
            ans = -1;
            break;
        }
//        cout << "in: " << in[i] << "  dep: " << dep[i] << endl;
    }
    return ans;
}

int main(){
    int t; scanf("%d", &t);
    while (t --){
        init();
        scanf("%d", &n);
        for (int i=1; i<=n; i++){
            int k; scanf("%d", &k);
            while (k --){
                int v; scanf("%d", &v);
                adde(v, i);
                in[i] ++;
            }
        }
        
        int ans = topsort();
//        printf("!!!!!   ");
        printf("%d\n", ans);
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值