【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;
}