http://poj.org/problem?id=3683
poj bits不能用就算了,结果auto也不能用= =,直接去牛客上过了,舒服
这题构图很简单,每个仪式只有两种时间,那么n^2看冲突就行了,注意如果一个仪式的某一个时间段会跟另一个仪式的两个时间段冲突,那么这个时间段就是不可选的。
这题关键是构造方案,传统的2-sat构造方案都是强联通分量缩点以后按反向图跑拓扑排序,我们可以知道一个强联通分量中的点全部都得是一种取值,因为确定了一个其他的也确定了,因为2-sat的关系是某个点取值为a时,另一个点必须取值为b这样的命题条件,那我们知道,如果选择反向图跑拓扑排序,零出度的点选择以后不会导致任何其他的点被选,那么这样一定是可行的,
lyd在蓝书上给出了另一种方法,因为tarjan算法本身得到的强联通分量编号是从小到大事自顶向下的,所以我们可以根据编号的大小来判断。
因为tarjan缩点后在有向图中,处于越末端的强连通分量的值越小,所以我们更应该选他,于是我们只需要考虑对于每个集合中的两种选择,哪一个强连通分量的编号越小,就应该选他,因为每个集合中只能选一个,肯定优先选处于正向图末端的,选了这个点那么影响就越小。而如果这两个点所在dcc没有路径,那么就无所谓了,随便选一个,这样的写法也是没错的。
#include<bits/stdc++.h>
using namespace std;
const int maxl=2e3+10;
int n,m,cnt,top,ind,ff;
bool ansflag;
int s[maxl],dfn[maxl],low[maxl],f[maxl];
int opp[maxl],ans[maxl];
struct node
{
int st[2],ed[2],c;
}a[maxl];
vector <int> e[maxl];
bool in[maxl];
char ch[10],ch1[10],ch2[10];
inline void add(int u,int v)
{
e[u].push_back(v);
}
inline int get_min()
{
return ((ch[0]-'0')*10+(ch[1]-'0'))*60+(ch[3]-'0')*10+ch[4]-'0';
}
inline bool cnfl(int i,int p,int j,int q)
{
return max(a[i].st[p],a[j].st[q])<min(a[i].ed[p],a[j].ed[q]);
}
inline void prework()
{
ind=0;top=0;ff=0;cnt=0;
for(int i=1;i<=2*n;i++)
{
dfn[i]=0,low[i]=0,in[i]=false;
opp[i]=0;ans[i]=0;
e[i].clear();
}
for(int i=1;i<=n;i++)
{
scanf("%s",ch);
a[i].st[0]=get_min();
scanf("%s",ch);
a[i].ed[1]=get_min();
scanf("%d",&a[i].c);
a[i].ed[0]=a[i].st[0]+a[i].c;
a[i].st[1]=a[i].ed[1]-a[i].c;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)
{
if(cnfl(i,0,j,0) && cnfl(i,0,j,1))
add(i,i+n);
else
{
if(cnfl(i,0,j,0))
add(i,j+n);
if(cnfl(i,0,j,1))
add(i,j);
}
if(cnfl(i,1,j,0) && cnfl(i,1,j,1))
add(i+n,i);
else
{
if(cnfl(i,1,j,0))
add(i+n,j+n);
if(cnfl(i,1,j,1))
add(i+n,j);
}
}
}
inline void tarjan(int u)
{
dfn[u]=low[u]=++ind;s[++top]=u;in[u]=true;
for(auto v : e[u])
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in[v])
low[u]=min(low[u],dfn[v]);
if(dfn[u]==low[u])
{
ff++;int v;
do
{
v=s[top--];
f[v]=ff;in[v]=false;
}while(u!=v);
}
}
inline void mainwork()
{
ansflag=true;ind=0;
for(int i=1;i<=2*n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
{
if(f[i]==f[i+n])
{
ansflag=false;
return;
}
opp[i]=n+i,opp[n+i]=i;
}
for(int i=1;i<=2*n;i++)
ans[i]=f[i]>f[opp[i]];
}
inline void get_ch1(int x)
{
int hh=x/60,mm=x%60;
ch1[0]=hh/10+'0';
ch1[1]=hh%10+'0';
ch1[2]=':';
ch1[3]=mm/10+'0';
ch1[4]=mm%10+'0';
}
inline void get_ch2(int x)
{
int hh=x/60,mm=x%60;
ch2[0]=hh/10+'0';
ch2[1]=hh%10+'0';
ch2[2]=':';
ch2[3]=mm/10+'0';
ch2[4]=mm%10+'0';
}
inline void print()
{
if(!ansflag)
puts("NO");
else
{
puts("YES");
for(int i=1;i<=n;i++)
{
if(ans[i]==0)
{
get_ch1(a[i].st[0]);
get_ch2(a[i].ed[0]);
}
else
{
get_ch1(a[i].st[1]);
get_ch2(a[i].ed[1]);
}
for(int j=0;j<5;j++)
printf("%c",ch1[j]);
putchar(' ');
for(int j=0;j<5;j++)
printf("%c",ch2[j]);
puts("");
}
}
}
int main()
{
//freopen("12.in","r",stdin);
while(~scanf("%d",&n))
{
prework();
mainwork();
print();
}
return 0;
}