【Tarjan】POJ 2942 —— Knights of the Round Table

探讨了在骑士中寻找符合条件的奇环问题,通过构建补图和使用Tarjan算法求解点双连通分量,进而判断骑士的合法性。采用交替染色法判断奇环存在性。

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

题目传送门

题目中给出的是骑士中矛盾关系,可以转换一下,得到原图的补图.然后观察题目中的条件,即选择的骑士数是奇数,并且相邻之间不矛盾.对应到现在的补图上,即寻找一个奇环,使得环的大小大于等于3.也就是说,只要一个骑士能够出现在一个符合条件的奇环中那么这个骑士便是合法.

首先用Tarjan将点双连通分量全部求出,对于一个点双连通分量,可以利用交替染色的方法判断是否存在奇环,如果存在一个奇环那么这个点双连通分量中的所有点都满足要求.

证明:假设一个点双连通分量重存在一个奇环,剩下的部分是一个偶环,那么根据点双连通分量的性质,那么就可以并成一个大的奇环.如果剩下的部分是一个奇环,那么两个奇环都可以满足要求.然后类推下去,即可得到,一个点双连通分量中存在一个奇环则满足要求.

#include<cstdio>
#include<algorithm>
using namespace std;

const int MAXN=1005;

int n,m,dcnt,top;
int dfn[MAXN],low[MAXN],vis[MAXN];
int ban[MAXN][MAXN],co[MAXN];
int head[MAXN],ecnt;
struct edge{
    int v,nxt;
}E[MAXN*MAXN*2];
struct node{
    int u,v,tag;
    node(){}
    node(int _u,int _v,int _tag):u(_u),v(_v),tag(_tag){}
}sta[MAXN*2];

void addedge(int u,int v){
    E[++ecnt].v=v,E[ecnt].nxt=head[u];
    head[u]=ecnt;
}

void Tarjan(int u,int fa=0){
    dfn[u]=low[u]=++dcnt;
    for(int i=head[u];i;i=E[i].nxt){
        int v=E[i].v;
        if(!dfn[v]){
            int pre=top;
            sta[++top]=node(u,v,0);
            co[v]=co[u]^1;
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]){
                int r=top,flag=0;
                while(top!=pre)if(sta[top--].tag)flag=1;
                while(r!=pre){
                    vis[sta[r].u]|=flag;
                    vis[sta[r].v]|=flag;
                    r--;
                }
            }
        }
        else if(v!=fa){
            low[u]=min(low[u],dfn[v]);
            if(co[u]==co[v]){
                vis[u]=vis[v]=1;
                if(dfn[u]>dfn[v])
                    sta[++top]=node(u,v,1);
            }
        }
    }
}

int main(){
    while(~scanf("%d%d",&n,&m)&&(n||m)){
        ecnt=dcnt=top=0;
        for(int i=1;i<=n;i++){
            head[i]=vis[i]=dfn[i]=low[i]=0;
            for(int j=1;j<=n;j++) ban[i][j]=0;
        }
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            ban[x][y]=ban[y][x]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(!ban[i][j]&&i!=j) addedge(i,j);
        for(int i=1;i<=n;i++)
            if(!dfn[i]){
                top=dcnt=0;
                co[i]=0;
                Tarjan(i);
            }
        int ans=0;
        for(int i=1;i<=n;i++)
            if(!vis[i]) ans++;
        printf("%d\n",ans);
    }
}

1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值