uva 1146 Now or late (暴力2-SAT)

/*
裸地2-SAT问题 关键是模型转化
最小的最大 显然二分 关键是Judge的时候怎么判断
每个航班是早是晚直接影响判断
早晚只能选一个 如果我们定义bool变量xi表示 i航班是否早到
每个航班虚拟出两个点2*i 2*i+1 分别表示是否早到
然后就可以假设某个航班早到然后推导出一定连得某些边
然后就开始选点 尝试这个点选不选 看看最后是否合法
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 4400
using namespace std;
int n,l,r,g[maxn][3],f[maxn],ans,c,s[maxn];
vector<int>G[maxn];
int Abs(int a)
{
    return a<0?-a:a;
}
void Add(int x,int y)
{
    G[x^1].push_back(y);G[y^1].push_back(x);
}
bool Dfs(int x)
{
    if(f[x^1])return 0;if(f[x])return 1;
    f[x]=1;s[c++]=x;
    for(int i=0;i<G[x].size();i++)
      if(!Dfs(G[x][i]))return 0;
    return 1;
}
bool Solve()//选点
{
    for(int i=0;i<n*2;i+=2)
      {
          if(f[i]||f[i+1])continue;c=0;//表示同一航班的两个点只选一个
        if(!Dfs(i))
          {
            while(c>0)f[s[--c]]=0;//撤销
            if(!Dfs(i+1))return 0;
          }
      }
    return 1;
}
bool Judge(int x)
{
    for(int i=0;i<n*2;i++)G[i].clear();
    memset(f,0,sizeof(f));
    for(int i=0;i<n;i++)for(int a=0;a<2;a++)
      for(int j=i+1;j<n;j++)for(int b=0;b<2;b++)
        if(Abs(g[i][a]-g[j][b])<x)
        //i*2+a 不能和 j*2+b 同时选  那就i*2+a连j*2+(b^1)  j*2+b连i*2+(a^1)
          Add(i*2+(a^1),j*2+(b^1));
    return Solve();
}
int main()
{
    while(scanf("%d",&n)==1&&n)
      {
          l=r=ans=0;
          for(int i=0;i<n;i++)
            for(int j=0;j<2;j++)
              {
                scanf("%d",&g[i][j]);
                r=max(r,g[i][j]);
            }
          while(l<=r)
            {
                int mid=(l+r)/2;
                if(Judge(mid))
                  {
                      ans=mid;l=mid+1;
              }
            else r=mid-1;
          }
        printf("%d\n",ans);
      }
    return 0;
}
时间: 2024-08-29 20:56:41

uva 1146 Now or late (暴力2-SAT)的相关文章

UVA 1146 Now or later

二分时间+2sat 边加多了....RE了好久...... Now or later Time Limit: 9000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   [Go Back]   [Status] Description As you must have experienced, instead of landing immediately, an aircraft sometimes waits

【UVA】12169-Disgruntled Judge(暴力or欧几里得)

可能由于后台数据的原因,这道题直接暴力枚举a,b进行判断也能过,不过跑的时间长,效率太差了. 14021006 12169 Disgruntled Judge Accepted C++ 0.876 2014-08-11 08:46:28 不说了,比较无脑. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #incl

uva 10825 - Anagram and Multiplication(暴力)

题目链接:uva 10825 - Anagram and Multiplication 题目大意:给出m和n,要求找一个m位的n进制数,要求说该数乘以2~m中的任意一个数的结果是原先数各个位上数值的一个排序. 解题思路:枚举最后一位数,然后用这个数去乘以2~m并对n取模,然后得到的数一定就是这个数的组成,暴力搜索一下并判断. #include <cstdio> #include <cstring> #include <algorithm> using namespace

UVA 1146 - Now or later(2-SET)

UVA 1146 - Now or later 题目链接 题意:n个飞机,每个飞机有一个早到时间和一个晚到时间,问怎么安排飞机,使得飞机到的间隔的最小值最大 思路:二分答案,然后利用2-set去判断,如果两个飞机的两个时刻间隔比这个时刻小,那么就是表示不能同时满足这两个条件,就加一条xi^xj的边进去,然后利用2-SET判定一下 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include &l

uva 11256 - Repetitive Multiple(gcd+暴力)

题目链接:uva 11256 - Repetitive Multiple 题目大意:给定一个数n,要求找到最小的k,使得k?n为题目中定义的重复数字. 解题思路:枚举k?n的循环节长度,比如当前枚举为2,那么一次判断u=1001,1001001,1001001001 ...,取d = gcd(n,u), 那么k = u / d, a = n / d (因为n?k=u?a)并且保证a的长度为2,所以k和a要同时扩大相应倍数.枚举过程中为何k. #include <cstdio> #include

uva 646 - The Gourmet Club(暴力)

题目链接:uva 646 - The Gourmet Club 题目大意:有16个人参加聚会,聚会一共5天,每天有4桌,每桌4个人,一起吃饭的4个人会互相认识.现在要安排座位使得16个任意两个人都互相认识.给出前三天的安排,求后两天的安排. 解题思路:任意两个人之间肯定只能同桌一次.所以根据这个条件,只要枚举出第4天的第1桌的情况,就可推导出所有的,或者是矛盾. 在Poj和Zoj上都过了,uva上过不了,求大神指教. #include <stdio.h> #include <string

UVa 11210 Chinese Mahjong (暴力,递归寻找)

题意:这个题意.有点麻烦,就是说给定13张牌,让你求能“听”的牌.(具体的见原题) 原题链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2151 析:看到这个题,真是麻烦啊,我又不懂麻将,看了好久才明白什么是“听”.分析一下思路. 首先对所有的牌都进行编号,然后暴力,首先的是先判断是哪个是将,然后再进一步判断, 哪一个是刻子,和顺子

uva 140 Bandwidth (全排列+暴力枚举)

uva 140 Bandwidth Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an ordering on the elements in V, then the bandwidth of a node v is defined as the maximum distance in the ordering between v and any node to which it

uva 270 Lining Up(暴力)

这道题目我是暴力做出来的,复杂度是n^3,因为数组做多有700组,大约可以用这个复杂度,虽然严格来说500多才 是正常的,每次都是选择两个坐标然后确定一条直线,然后遍历一下其他点,用叉积形式判一下是否在一条直线上就ok 啦,网上说可以用极角排序来解,复杂度是n^2logn然而我看了看并没有想学的欲望...以后再学吧,,,还用到了 sscanf函数,看别人这样用的,就是在一个数组里匹配想要的类型...这题比较坑的就是输入了.每两个输出之间 有空行,最后一组后面不能加空行...而且坐标输入之前有空行