强连通算法推断是否满足2-sat,然后反向建图,拓扑排序+染色。
一种选择是从 起点開始,还有一种是终点-持续时间那个点 開始。
若2个婚礼的某2种时间线段相交,则有矛盾,建边。
easy出错的地方就在于推断线段相交。
若s1<e2&&s2<e1则相交
输出路径的做法能够參考论文2-SAT解法浅析
#include <iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<algorithm> #include<queue> using namespace std; #define MAXN 5555 #define MAXM 3000010 struct node { int to,next; }edge[MAXM]; int head[MAXN],en; int low[MAXN],dfn[MAXN],stack[MAXN],cho[MAXN],top,set[MAXN],col,num,color[MAXN],counts[MAXN]; bool vis[MAXN],instack[MAXN]; int n; int m; void addedge(int a,int b) { edge[en].to=b; edge[en].next=head[a]; head[a]=en++; } int son[MAXN]; void tarjan(int u) { vis[u]=1; dfn[u]=low[u]=++num; instack[u]=true; stack[++top]=u; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!vis[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(dfn[v],low[u]); } if(dfn[u]==low[u]) { int j; col++; do { j=stack[top--]; instack[j]=false; set[j]=col; } while (j!=u); } } void init() { en=top=col=num=0; memset(head,-1,sizeof(head)); memset(instack,0,sizeof(instack)); memset(vis,0,sizeof(vis)); memset(set,-1,sizeof(set)); memset(color,0,sizeof(color)); memset(counts,0,sizeof(counts)); memset(cho,0,sizeof(cho)); } struct node2 { int st,ed,la; }p[2005]; vector<int> g[2005]; void topsort() { queue<int> q; for(int i=1;i<=col;i++) { if(counts[i]==0) q.push(i); } while(!q.empty()) { int j=q.front(); if(!color[j]) color[j]=1,color[son[j]]=-1; q.pop(); for(int k=0;k<g[j].size();k++) { if(--counts[g[j][k]]==0) q.push(g[j][k]); } } } void print(int t1,int t2) { printf("%02d:%02d",t1/60,t1%60); printf(" %02d:%02d\n",t2/60,t2%60); } int main() { int a,b,c,d,e; while(~scanf("%d",&n)) { init(); for(int i=1;i<=n;i++) { scanf("%d:%d%d:%d%d",&a,&b,&c,&d,&e); p[i].st=a*60+b; p[i].ed=c*60+d; p[i].la=e; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) continue; if(p[i].st<p[j].st+p[j].la && p[i].st+p[i].la>p[j].st) {addedge(i,j+n);} if(p[i].st<p[j].ed && p[i].st+p[i].la>p[j].ed-p[j].la) {addedge(i,j);} if(p[i].ed-p[i].la<p[j].st+p[j].la && p[i].ed>p[j].st) {addedge(i+n,j+n);} if(p[i].ed-p[i].la<p[j].ed && p[i].ed>p[j].ed-p[j].la) {addedge(i+n,j);} } } for(int i=1;i<=n*2;i++) if(!vis[i])tarjan(i); int ok=1; for(int i=1;i<=n;i++) { if(set[i]==set[i+n]) {ok=0;break;} son[set[i]]=set[i+n]; son[set[i+n]]=set[i]; } if(ok==0) {puts("NO");continue;} else puts("YES"); for(int i=1;i<=col;i++) g[i].clear(); for(int i=1;i<=2*n;i++) for(int j=head[i];~j;j=edge[j].next) if(set[i]!=set[edge[j].to]) { g[set[edge[j].to]].push_back(set[i]); counts[set[i]]++; } topsort(); for(int i=1;i<=2*n;i++) { if(color[set[i]]==1) cho[i]=1; } for(int i=1;i<=n;i++) { if(cho[i]) print(p[i].st,p[i].st+p[i].la); else print(p[i].ed-p[i].la,p[i].ed); } } return 0; } /* 3 08:00 09:00 30 08:15 09:00 20 08:00 09:00 30 */