输出方案好烦啊 代码超级多~第一次写这种代码,照着别人的代码打的。。
建图:
对于婚礼i和婚礼j,i表示开始主持,i`表示结束主持,j也是一样
枚举每一对不同的i和j,
如果i和j冲突,连接ij`
如果i和j`冲突,连接ij
如果i`和j冲突,连接i`j`
如果i`和j冲突,连接i`j
输出方案:
我们可以把处在同一个强连通分量中的点和边缩成一个点,得到新的有向图G1。然后,我们把G中的所有弧反向,得到图G2。
我们把G中所有顶点置为“未着色”。按照拓扑顺序重复下面的操作:
1、选择第一个未着色的顶点x。把x染成红色。
2、把所有与x矛盾的顶点(如果存在bi,~bi∈B ,且bi属于x代表的强连通分量,~bi属于代表y的强连通分量,那么x和y就是互相矛盾的顶点)及其子孙全部全部染成蓝色。
3、重复操作1和2,直到不存在未着色的点为止。此时,G2中被染成红色的点在图G中对应的顶点集合,就对应着该2-SAT的一组解。
此实现可以递归。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stack>
#define maxn 2010
#define maxe maxn*maxn*3
using namespace std;
struct node
{
int v,next;
}edge[maxe];
int n;
int s[maxn],t[maxn],seq[maxn];
int cnt,head1[maxn],head2[maxn],head3[maxn];
int scc,idex,dfn[maxn],low[maxn],belong[maxn];
int top,sstack[maxn];
bool instack[maxn],vis[maxn];
int d[maxn],col[maxn];
void addedge(int u,int v,int *head)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void tarjan(int u)
{
dfn[u]=low[u]=++idex;
sstack[++top]=u;
instack[u]=1;
for(int i=head1[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(dfn[v]==0)
{
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(instack[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
scc++;
while(1)
{
int tmp=sstack[top--];
addedge(scc,tmp,head3);
instack[tmp]=0;
belong[tmp]=scc;
if(tmp==u)
break;
}
}
}
void build()
{
int i,j;
for(i=1;i<=2*n;i++)
{
for(j=head1[i];j!=-1;j=edge[j].next)
{
int v=edge[j].v;
if(belong[i]!=belong[v])
{
addedge(belong[v],belong[i],head2);
}
}
}
}
bool ok(int i,int j)
{
if(s[i]>=t[j]||t[i]<=s[j])
return false;
return true;
}
bool check()
{
int i;
for(i=1;i<=n;i++)
{
if(belong[i<<1]==belong[i*2-1])
return false;
}
return true;
}
void topo()
{
int i,j;
top=0;
stack<int> sta;
for(i=1;i<=scc;i++)
{
for(j=head2[i];j!=-1;j=edge[j].next)
{
d[edge[j].v]++;
}
}
for(i=1;i<=scc;i++)
{
if(!d[i])
sta.push(i);
}
while(!sta.empty())
{
int u=sta.top();
sta.pop();
seq[++top]=u;
for(i=head2[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
d[v]--;
if(!d[v])
sta.push(v);
}
}
}
void paint(int u)
{
int k;
for(k=head2[u];k!=-1;k=edge[k].next)
{
if(col[edge[k].v]==0)
{
col[edge[k].v]=-1;
paint(edge[k].v);
}
}
}
void color()
{
int i,j,k;
for(j=1;j<=top;j++)
{
int u=seq[j];
if(col[u]==0)
{
col[u]=1;
for(i=head3[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(col[belong[((v-1)^1)+1]]==0)
{
col[belong[((v-1)^1)+1]]=-1;
paint(belong[((v-1)^1)+1]);
}
}
}
}
}
void print()
{
int i,j;
for(i=1;i<=n;i++)
{
if(col[belong[i*2]]==1)
{
printf("%02d:%02d %02d:%02d\n",s[i*2]/60,s[i*2]%60,t[i*2]/60,t[i*2]%60);
}
else
{
printf("%02d:%02d %02d:%02d\n",s[i*2-1]/60,s[i*2-1]%60,t[i*2-1]/60,t[i*2-1]%60);
}
}
}
int main()
{
freopen("in.txt","r",stdin);
int i,j;
scanf("%d",&n);
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(head3,-1,sizeof(head3));
cnt=0;
for(i=1;i<=n;i++)
{
int u,v,tmp;
scanf("%d:%d",&u,&v);
s[2*i-1]=u*60+v;
scanf("%d:%d",&u,&v);
t[2*i]=u*60+v;
scanf("%d",&tmp);
t[2*i-1]=s[2*i-1]+tmp;
s[2*i]=t[2*i]-tmp;
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(ok(2*i,2*j))
{
addedge(2*i,2*j-1,head1);
addedge(2*j,2*i-1,head1);
}
if(ok(2*i-1,2*j)){
addedge(2*i-1,2*j-1,head1);
addedge(2*j,2*i,head1);
}
if(ok(2*i,2*j-1)){
addedge(2*i,2*j,head1);
addedge(2*j-1,2*i-1,head1);
}
if(ok(2*i-1,2*j-1)){
addedge(2*i-1,2*j,head1);
addedge(2*j-1,2*i,head1);
}
}
}
scc=0;
for(i=1;i<=2*n;i++)
{
if(!dfn[i])
tarjan(i);
}
if(!check())
printf("NO\n");
else
{
printf("YES\n");
build();
topo();
color();
print();
}
return 0;
}