Wannafly挑战赛27

本文深入解析了算法竞赛中两种常见问题的解决策略。首先,针对数值组合问题,介绍了如何利用完全平方数特性优化搜索,通过预处理和统计技巧提高效率。其次,对于图论问题,阐述了判断二分图的方法,通过奇环检测确定最少染色数量,有效解决了复杂图的染色问题。

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

题目链接

A题:我们可以发现,ai+aj的最大值为2e5,显然这其中只有sqrt(2e5)个完全平方数。那么我们只需要枚举这个范围内的完全平方数 x,统计有多 少 ai + aj = x。这显然可以一边扫,一边用一个数组来统计。

//
//  main.cpp
//  wzazzy
//
//  Created by apple on 2018/10/23.
//  Copyright © 2018年 apple. All rights reserved.
//

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<bitset>
#include<vector>
using namespace std;
typedef long long int ll;
const int maxn =200000+5;
const int maxm=10000;
const int mod =1e9+7;
const int INF=0x3f3f3f3f;
//**********************************
int x;int a[maxn];
int main()
{
    int n;scanf("%d",&n);ll ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        for(int j=1;j*j<=2E5;j++)
            if(j*j>=x) ans+=a[j*j-x];
        a[x]++;
    }
    printf("%lld\n",ans);
    return 0;
}

B题:

首先可以知道,如果一张图是二分图最优的染色方案是黑白染色,否则 需要 3 种颜色。

那么只需要判断这张图是否是二分图即可,判断方式就是寻找有没有奇 环。

//
//  main.cpp
//  wzazzy
//
//  Created by apple on 2018/10/23.
//  Copyright © 2018年 apple. All rights reserved.
//


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<vector>

using namespace std;
const int maxn = 2e5;
struct edge{int to,isb,rev;};//isb标记桥,rev记录反向边
int n,m;
vector<edge> G[maxn];
int color[maxn],dfs_clock,pre[maxn],low[maxn],vis[maxn],iscut[maxn];
void add_edge(int a,int b)
{
    edge u,v;
    u.to = b,u.isb = 0,v.to = a,v.isb = 0,u.rev = G[b].size(),v.rev = G[a].size();
    G[a].push_back(u);
    G[b].push_back(v);
}
bool bipartite(int u)
{
    for(int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i].to;
        if(!color[v])
        {
            color[v] = 3 - color[u];
            if(!bipartite(v))
                return false;
        }else if(color[v] == color[u])
            return false;
    }
    return true;
}
int dfs(int u,int fa)
{
    int lowu = pre[u] = ++dfs_clock;
    int child = 0;
    for(int i = 0; i < G[u].size();i++)
    {
        int v = G[u][i].to;
        if(!pre[v])
        {
            child++;
            int lowv = dfs(v,u);
            lowu = min(lowu,lowv);
            if(lowv > pre[u])
            {
                G[u][i].isb = 1;
                G[v][G[u][i].rev].isb = 1;
                // printf("%d -> %d\n",u,v);
            }
        }else if(pre[v] < pre[u] && v!=fa)
            lowu = min(lowu,pre[v]);
    }
    if(fa < 0 && child == 1) iscut[u] = 0;
    low[u] = lowu;
    return lowu;
}
int ncnt,mcnt;
void dfs2(int u)
{
    //  printf("u = %d fa = %d\n",u,fa);
    for(int i = 0; i < G[u].size();i++)
    {
        if(G[u][i].isb)continue;
        int v = G[u][i].to;
        //printf("%d--%d\n",u,v);
        mcnt++;
        //  printf("%d -> %d\n",u,v);
        if(!vis[v])
        {
            ncnt++;
            vis[v] = true;
            dfs2(v);
        }
    }
}
int main()
{
    
    bool odd = false;
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n ;i++)
        G[i].clear();
    memset(color,0,sizeof(color));
    memset(pre,0,sizeof(pre));
    memset(vis,false,sizeof(vis));
    dfs_clock = 0;
    for(int i = 0; i < m ;i ++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add_edge(u,v);
    }
    for(int i =1; i <= n; i++)
        if(!color[i])
        {
            color[i] = 1;
            if(!bipartite(i))
                odd = true;
        }
    if(odd)
        printf("3");
    else
        printf("2");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值