LA 3211 Now or Later(2-SAT问题)

题目大意:

    N架飞机需要着陆,每架飞机都有一个早着陆时间和晚着陆时间,安排飞机着陆方式,使得相邻两个着陆时间间隔的最小值最大。

解题思路:

   "最小值最大问题”典型的处理方式就是二分查找最终答案P,这样将问题转化为是否存在一个安排方案,使得任意两个相邻着陆时间的间隔都不小于P。

这个问题可以进一步转化为一个2-SAT问题,将两个时间差小于P的点相连,判断是否存在解。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define LL long long
using namespace std;
const int maxn = 10000 + 10;
class TwoSAT
{
public:
	int n;
	vector<int> G[maxn*2];
	bool mark[maxn*2];
	int S[maxn*2] , c;
	bool dfs(int x)
	{
		if(mark[x^1]) return false;
		if(mark[x]) return true;
		mark[x] = true;
		S[c++] = x;
		for(int i=0;i<G[x].size();i++)
			if(!dfs(G[x][i])) return false;
		return true;
	}
	void init(int n)
	{
		this->n = n;
		for(int i=0;i<=2*n;i++) G[i].clear();
		memset(mark,0,sizeof(mark));
	}
	void AddEdge(int x,int y)
	{
		G[x^1].push_back(y);
		G[y^1].push_back(x);
	}
	bool solve()
	{
		for(int i=0;i<n*2;i+=2)
			if(!mark[i] && !mark[i+1])
			{
				c = 0;
				if(!dfs(i))
				{
					while(c > 0) mark[S[--c]] = false;
					if(!dfs(i+1)) return false;
				}
			}
		return true;
	}
};
TwoSAT g;
int n , T[maxn][2];
bool test(int limit)
{
	g.init(n);
	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(T[i][a] - T[j][b]) < limit)
						g.AddEdge(2*i+a,2*j+b);
				}
			}
		}
	}
	return g.solve();
}
int main()
{
	while(scanf("%d",&n)!=EOF && n)
	{
		int L = 0 , R = 0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<2;j++)
			{
				scanf("%d",&T[i][j]);
				R = max(R,T[i][j]);
			}
		}
		while(L < R)
		{
			int m = L + (R - L + 1) / 2;
			if(test(m)) L  = m ;
			else R = m - 1;
		}
		printf("%d\n",R);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值