2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛

本文提供了多项比赛题目的解析,包括猴子找香蕉问题、椰子传递稳定性判断、半连续数查找等,涵盖简单到复杂的多种算法题型,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接


 暂无,作为学校里倒数的队伍,我们参加比赛就是提高自己,本次比赛题目其实很友好,但是我们队伍却不能把握题目的脉络,暴露了极大的问题。

一些题解


A Banana

 本题的题意是给定不同的猴子喜欢的不同的香蕉种类,和不同种类的香蕉在不同的地方可以拿到,问猴子可以在那些地方拿到自己喜欢的香蕉。
 签到题,队友直接无脑三重循环输出即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int n,m;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        bool mon[55][55];
        bool place[55][55];
        memset(mon,0,sizeof(mon));
        memset(place,0,sizeof(place));
        int x,y;
        int mxm=0,mxp=0,mxb=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            mon[x][y]=1;
            mxm=max(mxm,x);
            mxb=max(mxb,y);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            place[y][x]=1;
            mxp=max(mxp,y);
        }
        for(int i=1;i<=mxm;i++)
        {
            for(int j=1;j<=mxp;j++)
            {
                for(int k=1;k<=mxb;k++)
                {

                    if(mon[i][k]==1&&place[j][k]==1)
                        {
                            printf("%d %d\n",i,j);
                            break;
                        }
                }

            }
        }
        printf("\n");
    }

    return 0;
}

C Coconut

 签到题。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i, s, t) for(int i = s;i <= t;i++)
#define rap(i, s, t) for(int i = s;i >= t;i--)
using namespace std;
int C[1005], D[1005];
int N, b;
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &N, &b);
        rep(i, 1, N)
            scanf("%d", &C[i]);
        rep(i, 1, N - 1)
            scanf("%d", &D[i]);
        int support = 0;
        int flag = 1;
        rep(i, 1, N - 1)
        {
            support += C[i];
            support -= D[i] * b;
            if(support < 0)
            {
                flag = 0;
                break;
            }
        }
        if(flag == 1)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

E Half-consecutive Numbers

 直接打表题

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
LL stan[23] = {
 1, 8, 49, 288, 1681, 9800, 57121, 332928, 1940449, 11309768, 65918161, 384199200, 2239277041, 13051463048, 76069501249, 443365544448, 2584123765441, 15061377048200, 87784138523761, 511643454094368, 2982076586042449, 17380816062160328, 101302819786919521};
int main()
{
    int t;
    scanf("%d", &t);
    int kase = 1;
    while(t--)
    {
        LL n;
        scanf("%lld", &n);
        for(int i = 0;i <= 22;i++)
            if(stan[i] >= n)
            {
                printf("Case #%d: %lld\n", kase++, stan[i]);
                break;
            }
    }
    return 0;
}

F Islands

 给你一些点的连通情况问你最少需要添加几条边可以让整个图的所有点相互连通。
 强连通模板题,直接强连通缩点,记录所缩的点的每个点是否有出度入度,之后分别统计没有出度和没有入度的点的个数,两个数据取大值就是答案。

#include <bits/stdc++.h>
#define MAXN 100010
using namespace std;
vector<int> G[MAXN];
int low[MAXN], dfn[MAXN];
int dfs_clock;
int belong[MAXN], scc_cnt;
vector<int> scc[MAXN];
stack<int> S;
bool Instack[MAXN];
int n, m;
void tarjan(int u, int fa)
{
    int v;
    low[u] = dfn[u] = ++dfs_clock;
    S.push(u);
    Instack[u] = true;
    for(int i = 0; i < G[u].size(); i++)
    {
        v = G[u][i];
        if(!dfn[v])
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
        }
        else if(Instack[v])
            low[u] = min(low[u], dfn[v]);
    }
    if(low[u] == dfn[u])
    {
        scc_cnt++;
        scc[scc_cnt].clear();
        while(1)
        {
            v = S.top(); S.pop();
            Instack[v] = false;
            belong[v] = scc_cnt;
            scc[scc_cnt].push_back(v);
            if(v == u) break;
        }
    }
}
void find_cut(int l, int r)
{
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(belong, 0, sizeof(belong));
    memset(Instack, false, sizeof(Instack));
    dfs_clock = scc_cnt = 0;
    for(int i = l; i <= r; i++)
        if(!dfn[i])
            tarjan(i, -1);
}
int in[MAXN], out[MAXN];
int main()
{
    int tt;
    scanf("%d", &tt);
    while(tt--)
    {
        scanf("%d%d", &n, &m);
        int s, t;
        for(int i = 1; i <= n; i++) G[i].clear();
        while(m--)
            scanf("%d%d", &s, &t), G[s].push_back(t);
        find_cut(1, n);
        for(int i = 1; i <= scc_cnt; i++) in[i] = out[i] = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j < G[i].size(); j++)
            {
                int u = belong[i];
                int v = belong[G[i][j]];
                if(u != v)
                    out[u]++, in[v]++;
            }
        }
        if(scc_cnt == 1)
        {
            printf("0\n");
            continue;
        }

        int sum_ind = 0, sum_outd = 0;
        for(int i = 1; i <= scc_cnt; i++)
        {
            if(in[i] == 0) sum_ind++;
            if(out[i] == 0) sum_outd++;
        }
        printf("%d\n", max(sum_ind, sum_outd));
    }
    return 0;
}

H Skiing

 题目是说给定一些路径问能连通的最长路径是多少。一开始写了一发搜索t掉了,之后队友开始搞最长路开始各种t各种wa各种段错误,后来我又改进了下搜索的方法,记忆化一下就过去了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i, s, t) for(int i = s;i <= t;i++)
#define rap(i, s, t) for(int i = s;i >= t;i--)
using namespace std;
int N, M;
int node[10005];
struct Edge
{
    int v, next, l;
}edge[100005];
int visit[10005];
int dis[10005];
int cnt_edge;
int ans;
int dfs(int u, int val)
{
    int sum = 0;
    visit[u] = 1;
    for(int i = node[u];i != -1;i = edge[i].next)
    {
        int v = edge[i].v;
        if(visit[v] == 1)
            sum = max(sum, dis[v] + edge[i].l);
        else
        {
            dfs(v, val + edge[i].l);
            sum = max(sum, dis[v] + edge[i].l);
        }
    }
    ans = max(ans, val + sum);
    dis[u] = sum;
    return sum;
}
void add_edge(int u, int v, int w)
{
    edge[cnt_edge].v = v;
    edge[cnt_edge].l = w;
    edge[cnt_edge].next = node[u];
    node[u] = cnt_edge++;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &N, &M);
        memset(node, -1, sizeof(node));
        memset(visit, 0, sizeof(visit));
        memset(dis, 0, sizeof(dis));
        cnt_edge = 0;
        rep(i, 1, M){
            int a, b, l;
            scanf("%d%d%d", &a, &b, &l);
            add_edge(a, b, l);
        }
        ans = 0;
        rep(i, 1, N){
            if(visit[i] == 0)
                dfs(i, 0);
        }
        printf("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值