算法:HDU 3715 Go Deeper(2-SAT + 二分)

【题目大意】

有一个递归代码:

go(int dep, int n, int m)

begin

    output the value of dep.

if dep < m and x[a[dep]] + x[b[dep]] != c[dep] then go(dep + 1, n, m)

end

关键是看第四行, 如果满足条件dep < m and x[a [dep]] + x[b[dep]] != c[dep] 那么就可以进入下一层递归, x数组只取{0, 1}, c数组取{ 0,1,2 }, 而a和b数组取0~m, m是最大能递归的层数,也是数组x的大小。  问最多能递归多少层?

【思 路】

对于每个x【i】, 只能取0或者1, 在每一层中如果满足条件就可以进入下一层,这个题非常像  poj 2723 , 做法也是一样的。

二分最多能递归的层数,然后对这些层数进行2-sat的建图, 判断即可。

【代码】

#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#define MP make_pair
#define SQ(x) ((x)*(x))
using namespace std;  

const int INF  = 0x3f3f3f3f;
const int MAXN = 10010;
const int VN = MAXN*2;
const int EN = VN*4;  

int n, m, s;
int a[MAXN], b[MAXN], c[MAXN];  

struct Graph{
    int size, head[VN];
    struct{int v, next; }E[EN];
    void init(){size=0; memset(head, -1, sizeof(head)); };
    void addEdge(int u, int v){
        E[size].v = v;
        E[size].next = head[u];
        head[u] = size++;
    }
}g;  

class Two_Sat{
public:
    bool check(const Graph& g, const int n){
        scc(g, 2*n);
        for(int i=0; i<n; ++i)
            if(belong[i] == belong[i+n])
                return false;
        return true;
    }
private:
    void tarjan(const Graph& g, const int u){
        int v;
        dfn[u] = low[u] = ++idx;
        sta[top++] = u;
        instack[u] = true;  

        for(int e=g.head[u]; e!=-1; e=g.E[e].next){
            v = g.E[e].v;
            if(dfn[v] == -1){
                tarjan(g, v);
                low[u] = min(low[u], low[v]);
            }else if(instack[v]){
                low[u] = min(low[u], dfn[v]);
            }
        }  

        if(dfn[u] == low[u]){
            ++bcnt;
            do{
                v = sta[--top];
                instack[v] = false;
                belong[v] = bcnt;
            }while(u != v);
        }
    }  

    void scc(const Graph& g, const int n){
        idx = top = bcnt = 0;
        memset(dfn, -1, sizeof(dfn));
        memset(instack, 0, sizeof(instack));
        for(int i=0; i<n; ++i){
            if(dfn[i] == -1)
                tarjan(g, i);
        }
    }  

private:
    int idx, top, bcnt;
    int dfn[VN], low[VN], sta[VN], belong[VN];
    bool instack[VN];
}sat;  

void buildGraph(int dep){
    g.init();
    for(int i=0; i<dep; ++i){
        int x=a[i], y=b[i];
        if(c[i]==0){
            g.addEdge(x, y+m);
            g.addEdge(y, x+m);
        }else if(c[i] == 1){
            g.addEdge(x, y);
            g.addEdge(x+m, y+m);
            g.addEdge(y, x);
            g.addEdge(y+m, x+m);
        }else if(c[i] == 2){
            g.addEdge(x+m, y);
            g.addEdge(y+m, x);
        }
    }  

}
int main(){  

    int nCase;
    scanf("%d", &nCase);  

    while(nCase--){  

        scanf("%d%d", &n, &m);  

        for(int i=0; i<m; ++i){
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
        }  

        int l=0, r=m+1, mid, ans;
        while(l < r){
            mid = (l + r) >> 1;
            buildGraph(mid);
            if(sat.check(g, m)){
                l = mid+1;
                ans = mid;
            } else r = mid;
        }
        printf("%d\n", ans);
    }  

    return 0;
}

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索数组
, 递归
, int
, include
, const
, head
递归二分查找算法
we need to go deeper、we need go deeper、go deeper、gosation、长沙分时租赁 sat go,以便于您获取更多的相关知识。

时间: 2024-11-01 12:43:54

算法:HDU 3715 Go Deeper(2-SAT + 二分)的相关文章

算法:HDU 3622 Bomb Game(2-SAT + 二分)

[题目大意] 要在坐标轴上放N次炸弹,每次可以选择两个位置中的一个位置放置,每个炸弹都可 以控制它的爆炸范围(以放置位置为圆心的半径为r的圆圈),问半径最大可以多少,使得任意两个炸弹的爆 炸范围都不重合. [思路] 类似与poj 2296 , 但是判断重合的方法容易多了,果断 1Y 注意精度问题. [代码] #include<iostream> #include<queue> #include<cstdio> #include<cstring> #inclu

《算法基础:打开算法之门》一3.1 二分查找

3.1 二分查找 在学习一些排序算法之前,首先学习二分查找,其中待查找的数组事先需要是有序的.二分查找的优点是从包含n个元素的数组中执行查找操作仅仅需要O(lgn)时间. 在书架那个例子中,当书架上的书已经按照作者名字从左向右依次排好序后才开始进行查找.我们将使用作者名字作为主关键字,现在让我们搜索下由Jonathan Swift所写的书.你可能已经推测到:因为作者的姓以"S"开头,"S"是字母表中的第19个字母,且19/26与3/4接近,因此你可能会浏览书架上位置

算法-HDU 1509 Windows Message Queue

问题描述 HDU 1509 Windows Message Queue 自己测试总刚觉没错,求高手帮忙,不知道哪错了,总wa.................................. 解决方案 import java.util.Comparator; import java.util.PriorityQueue; import java.util.Scanner; class Nod { String name; int val, pri; public Nod(String name

php 二分查找法算法详解

一.概念:二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功. 二.代

hdu 4430 Yukari&#039;s Birthday

点击打开链接hdu 4430 思路:枚举r+二分k 分析: 1 题目要求的是找到一组最小的r*k,如果r*k相同那么就找r最小的. 2 很明显k>=2,根据n <= 10^12,那么可以知道r的最大值r<50,所以只要枚举枚举r的值,然后二分k的大小找到所有的解,存入一个结构体里面,然后在对结构体排序,那么这样就可以得到最后的ans 3 注意题目说了中心点最多一个蜡烛,所以写二分的时候应该注意判断的条件: 4 还有可能计算得到结果超了long long直接变成负数所以应该对或则个进行判断

《大数据算法》一2.4 数组有序的判定算法

2.4 数组有序的判定算法 本节讨论数组有序的判定问题的判定算法. 1.问题的定义 数组有序的判定问题 输入:包含n个数的数组A. 输出:若A中元素单调递增则输出"是":否则输出"否". 首先看一下这个问题的定义,输出是判定的结果,这个数组是否有序?如果需要精确地回答这个问题,就需要访问n个数,时间是Ω(n).但是要求是设计亚线性算法,就是不访问所有的数据也能完成判定,所以采用近似算法. 要定义近似,需要用到ε-远离的概念.在这个问题中,ε-远离意味着必须删除大于ε

排序算法python实现

先列出一些算法复杂度的标识符号的意思, 最常用的是O,表示算法的上届,如 2n2 = O(n2 ), 而且有可能是渐进紧确的, 意思是g(n)乘上一个常数系数是可以等于f(n)的,就是所谓的a<=b.而o的区别就是非渐进紧确的,如2n = o(n2 ), o(n2 )确实可以作为2n的上届, 不过比较大, 就是所谓的a 其他符号表示了下届,和非渐进紧确的下届, a>=b, a>b 还有既是上届也是下届, 就是a=b Bubble Sort 冒泡排序效率是最低的, 对于list中任意一点,

【DP专辑】ACM动态规划总结

转载请注明出处,谢谢.   http://blog.csdn.net/cc_again?viewmode=list          ----------  Accagain  2014年5月15日 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力.建模抽象能力.灵活度. 本人动态规划博客地址:http://blog.csdn.net/cc_again/article/category/1261899 ******************

数据映射--映射概述

上周是硬件,本周终于来到软件领域,明确的欠一个帐,文件系统这块因为东西比较多,我还没完全总结好,先欠着~ 本周,让我们做一些准备,来谈谈映射.计算机就是个分型的系统,而映射这种数据结构,是计算机中非常基础和常见的一种数据结构, 从cpu到文件存储,再到分布式文件存储,其核心都是映射. 抄书: 映射就是: 使得对A中的每个元素a,按法则f,在B中有唯一确定的元素b与之对应,则称f为从A到B的映射,记作f:A→B. 哈哈,数学上的定义是最清晰和明确的.也可以写作y = f(x) 举个例子: 给定一个