【POJ3683】Priest John's Busiest Day

题目大意:给定 N 个操作,每个操作占用两个区间中的任意一个即可,求是否可以满足 N 项操作,且使得操作区间不重叠,若可以,输出一种具体方案。

题解:2-sat 模板题,区间覆盖的位置有些毒瘤,貌似题意没交代清楚?

代码如下

#include <cstdio>
#include <vector>
#include <utility>
#include <ctype.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=2010;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
	ll x=0,f=1;char ch;
	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
	return f*x;
}

vector<int> G[maxn];
int dfs_clk,dfn[maxn],low[maxn],stk[maxn],in[maxn],top;
int scc,cor[maxn];
int n,st[maxn],ed[maxn],len[maxn];
char s[10];

bool overlap(int a, int b, int c, int d) {
	if (a >= c&&a<d || b>c&&b <= d || a <= c&&b >= d) return 1;
	return 0;
}

void read_and_parse(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%s",s+1);
		st[i]=((s[1]-'0')*10+s[2]-'0')*60+(s[4]-'0')*10+s[5]-'0';
		scanf("%s",s+1);
		ed[i]=((s[1]-'0')*10+s[2]-'0')*60+(s[4]-'0')*10+s[5]-'0';
		scanf("%d",&len[i]);
	}
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++){
			if(overlap(st[i],st[i]+len[i],st[j],st[j]+len[j]))G[i].pb(j+n),G[j].pb(i+n);
			if(overlap(st[i],st[i]+len[i],ed[j]-len[j],ed[j]))G[i].pb(j),G[j+n].pb(i+n);
			if(overlap(ed[i]-len[i],ed[i],st[j],st[j]+len[j]))G[i+n].pb(j+n),G[j].pb(i);
			if(overlap(ed[i]-len[i],ed[i],ed[j]-len[j],ed[j]))G[i+n].pb(j),G[j+n].pb(i);
		}
}

void tarjan(int u){
	low[u]=dfn[u]=++dfs_clk;
	stk[++top]=u,in[u]=1;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
		else if(in[v])low[u]=min(dfn[v],low[u]);
	}
	if(low[u]==dfn[u]){
		++scc;int v;
		do{
			v=stk[top--],in[v]=0;
			cor[v]=scc;
		}while(u!=v);
	}
}

void solve(){
	for(int i=1;i<=n<<1;i++)if(!dfn[i])tarjan(i);
	for(int i=1;i<=n;i++)if(cor[i]==cor[i+n])return (void)puts("NO");
	puts("YES");
	for(int i=1;i<=n;i++){
		if(cor[i]<cor[i+n])
			printf("%02d:%02d %02d:%02d\n",st[i]/60,st[i]%60,(st[i]+len[i])/60,(st[i]+len[i])%60);
		else
			printf("%02d:%02d %02d:%02d\n",(ed[i]-len[i])/60,(ed[i]-len[i])%60,ed[i]/60,ed[i]%60);
	}
}

int main(){
	read_and_parse();
	solve();
	return 0;
}

posted @ 2019-03-31 21:06  shellpicker  阅读(139)  评论(0编辑  收藏  举报