CF1388A~D(DFS,拓扑排序)

A.Captain Flint and Crew Recruitment

题意:

定义了一种近似素数,当一个数可以用两个素数的乘积表示时,称他为近似素数。

现在请你把正整数n用四个不同的正整数的和表示,其中至少三个是近似素数。

题解:

直接分解成三个最小的近似素数和另外一个随便什么数的和即可。

#include<bits/stdc++.h>
using namespace std;
int t,n;
int main () {
    scanf("%d",&t);
    while (t--) {
        scanf("%d",&n);
        if (n<=30) {
            printf("NO
");
            continue;
        }
        printf("YES
");
        //printf("6 10 14 %d
",n-20); 
        if (n-30==6||n-30==10||n-30==14) {
            printf("6 10 15 %d
",n-31);
        }
        else {
            printf("6 10 14 %d
",n-30);
        }
    }
}
View Code

B.Captain Flint and a Long Voyage

题意:

给出一个长度n,请你找到最小的长度为n的十进制数x,使得它转换为2进制后的的数去掉最后n位尽可能大。

题解:

测智题,对我这种智商低的选手不友好。答案就是前3/4是9,后1/4是8。

#include<bits/stdc++.h>
using namespace std;
const int maxn=11010;
int t,n;
int main () {
    scanf("%d",&t);
    while (t--) {
        scanf("%d",&n);
        int tt=n/4;
        if (n%4) tt++;
        for (int i=1;i<=n-tt;i++)
            printf("9");
        for (int i=n-tt+1;i<=n;i++)
            printf("8");
        printf("
");
    }
}
View Code

C.Uncle Bogdan and Country Happiness

题意:

给出一棵树,每个节点代表一个城市,每个城市有人口。一开始所有人都在首都1。

给出一个序列h,表示猜测的每个城市的开心人数和不开心人数的差值。

现在所有人从首都1开始返回自己的家乡,他们保持同步,到自己家乡之后会停止,他们可以在任意时刻改变自己的心情,但变成不开心之后就永远不开心了。

询问是否可能h数组的情况出现。

题解:

首先统计出每个节点的子树人口数,以此排除无法构造差值的节点(比如奇偶性不同就无法构造)

然后通过给定的h[i]算出每个节点开心的人数,然后做第二遍DFS,看一下每个节点的开心的人数和它所有子节点的开心的人数之和,如果小于则不合法。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
vector<int> g[maxn];
typedef long long ll;
ll p[maxn];
ll h[maxn];
ll dfn[maxn];//记录每个城市的子树人口和 
ll wjm[maxn];//计算出每个节点必须开心的人数 
int t,n,m;
int f;
void dfs (int u,int pre) {
    dfn[u]=p[u];
    for (int v:g[u]) {
        if (v==pre) continue;
        dfs(v,u);
        dfn[u]+=dfn[v];
    }
}
void dfs1 (int u,int pre) {
    int sum=0;
    for (int v:g[u]) {
        if (v==pre) continue;
        dfs1(v,u);
        sum+=wjm[v];
    }
    //printf("%d %d %d
",u,wjm[u],sum);
    if (sum>wjm[u]) f=0;
}
int main () {
    scanf("%d",&t);
    while (t--) {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) g[i].clear(),dfn[i]=0;
        for (int i=1;i<=n;i++) scanf("%lld",p+i);
        for (int i=1;i<=n;i++) scanf("%lld",h+i);
        for (int i=1;i<n;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            g[x].push_back(y);
            g[y].push_back(x);
        }
        dfs(1,0);
        f=1;
        for (int i=1;i<=n;i++) {
        //    printf("%d %d
",dfn[i],h[i]);
            //if (dfn[i]-2*abs(h[i])<0) f=0;
            if (dfn[i]<h[i]||dfn[i]<-h[i]) f=0;
            if ((dfn[i]%2)^(abs(h[i])%2)) f=0; 
            ll x=(dfn[i]+h[i])>>1;
            wjm[i]=x;
        }
        dfs1(1,0);
        if (f)
            printf("YES
");
        else
            printf("NO
");
    }
}
View Code

D.Captain Flint and Treasure

题意:

给出两个序列a和b,一次操作你可以将ans+=a[i],a[b[i]]+=a[i]。询问最后ans的最大值。

题解:

拓扑排序,遇到负权值的节点就跳过,减少它给答案带来的贡献。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
typedef long long ll;
ll a[maxn];
int b[maxn];
int inDegree[maxn];
int n;
vector<int> g[maxn];
ll ans;
void topo () {
    queue<int> q;
    for (int i=1;i<=n;i++) 
        if (inDegree[i]==0) {
            q.push(i);
        }
    
    while (!q.empty()) {
        int u=q.front();
        q.pop();
        ans+=a[u];
        if (b[u]==-1) continue;
        if (a[u]>0) {
            g[u].push_back(b[u]);
            a[b[u]]+=a[u];
        }
        else {
            g[b[u]].push_back(u);
        }
        if (--inDegree[b[u]]==0) q.push(b[u]);
    }
    
}
int main () {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%lld",a+i);
    for (int i=1;i<=n;i++) {
        scanf("%d",b+i);
        if (b[i]>0) {
            inDegree[b[i]]++;
        }
    }
    topo();
    printf("%lld
",ans);
    vector<int> wjm;
    for (int i=1;i<=n;i++)
        for (int v:g[i]) inDegree[v]++;
    for (int i=1;i<=n;i++) if (inDegree[i]==0) wjm.push_back(i);
    for (int i=0;i<n;i++) {
        printf("%d ",wjm[i]);
        for (int v:g[wjm[i]]) 
            if (--inDegree[v]==0) wjm.push_back(v);
    }
}
View Code
原文地址:https://www.cnblogs.com/zhanglichen/p/13409696.html