P3007 [USACO11JAN]大陆议会The Continental Cowngress

本文解析了USACO竞赛题目“大陆议会”的算法思路,介绍了如何利用2-SAT算法结合Tarjan算法解决该问题,并给出了具体的代码实现。

P3007 [USACO11JAN]大陆议会The Continental Cowngress

题意: 给出 n 个法案, m 头牛的意见, 每头牛有两个表决 格式为 “支持或反对某法案”, 每头牛需要至少满足一个表决, 不可能成立的话输出 IMPOSSIBLE, 否则输出方案, Y代表能, N代表不能若是有的解中法案可以通过, 有些不能则输出“?”


哇这题确认过眼神, 遇上对的测评机莫名洛谷 \(RANK 1\)

首先若是没有输出 \(?\) 这题就是一个裸的 限制条件为或\(2-SAT\), 关键是我们如何处理这个 “可以在不同的解中为不同的状态”

回想一下在2-SAT里提到过的 ** \(Tarjan\) 的过程就是逻辑推理的过程 ,** 若是点 \(v\) 能由 \(u\) 到达, 那我们认为 满足意义 \(u\) 则一定需要满足意义 \(v\) , 那么我们很快就可以得到啥时候一个条件的两个状态(\(0\)\(1\))没得关系了: \(u\ ,\ v\) 两点不互达时, 他们之间无明确的互相限制关系

所以在确定有解以后, 我们在 \(Tarjan\) 后的 \(DAG\) 上对于一个法案的两种状态 \(dfs\) , 若不互通则此点状态任意
p.s:因为是 \(DAG\) 所以不用 \(vis[ ]\)数组
p.s.s:别忘了建新图的时候别搞自环。。。

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
typedef long long LL;
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 2000019,INF = 1e9 + 19;
int head[maxn][2],nume = 1;
struct Node{
    int v,dis,nxt;
    }E[maxn << 2][2];
void add(int u,int v,int dis, int o){
    E[++nume][o].nxt = head[u][o];
    E[nume][o].v = v;
    E[nume][o].dis = dis;
    head[u][o] = nume;
    }
int num, nr;
int DFN[maxn], LOW[maxn], INDEX;
int S[maxn], top;
bool ins[maxn];
int col[maxn], numc;
void Tarjan(int u){
    DFN[u] = LOW[u] = ++INDEX;
    S[++top] = u;ins[u] = 1;
    for(int i = head[u][0];i;i = E[i][0].nxt){
        int v = E[i][0].v;
        if(!DFN[v])Tarjan(v), LOW[u] = min(LOW[u], LOW[v]);
        else if(ins[v])LOW[u] = min(LOW[u], DFN[v]);
        }
    if(DFN[u] == LOW[u]){
        numc++;
        while(S[top + 1] != u){
            col[S[top]] = numc;
            ins[S[top--]] = 0;
            }
        }
    }
bool dfs(int u, int goal){
    if(u == goal)return 1;
    for(int i = head[u][1];i;i = E[i][1].nxt){
        int v = E[i][1].v;
        if(dfs(v, goal))return 1;
        }
    return 0;
    }
bool check(int c1, int c2){
    if(!dfs(c1, c2) && !dfs(c2, c1)){
        printf("?");
        return 1;
        }
    return 0;
    }
int main(){
    num = RD();nr = RD();
    int a, b, x, y;char c1, c2;
    for(int i = 1;i <= nr;i++){
        a = RD(), cin>>c1, b = RD(), cin>>c2;
        if(c1 == 'Y')x = 1;else x = 0;
        if(c2 == 'Y')y = 1;else y = 0;
        //<< 1 | 0 -> 0 , << 1 | 1 -> 1
        add(a << 1 | (x ^ 1), b << 1 | y, 1, 0);
        add(b << 1 | (y ^ 1), a << 1 | x, 1, 0);
        }
    for(int i = 2;i <= (num << 1 | 1);i++)if(!DFN[i])Tarjan(i);
    for(int i = 1;i <= num;i++){
        if(col[i << 1] == col[i << 1 | 1]){
            puts("IMPOSSIBLE");
            return 0;
            }
        }
    for(int u = 2;u <= (num << 1 | 1);u++){
        for(int i = head[u][0];i;i = E[i][0].nxt){
            int v = E[i][0].v;
            if(col[u] == col[v])continue;
            add(col[u], col[v], 1, 1);
            }
        }
    for(int i = 1;i <= num;i++){
        if(check(col[i << 1], col[i << 1 | 1]))continue;
        if(col[i << 1] < col[i << 1 | 1])printf("N");
        else printf("Y");
        }
    puts("");
    return 0;
    }

转载于:https://www.cnblogs.com/Tony-Double-Sky/p/9461406.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值