题目大意
有$n$个时间安排,可以安排到$2$个时间,问是否可以将时间错开,若能,输出一种方案。
试题分析
$O(n^2)$暴力判断两者是否能在同一个时间安排,若有两段时间$(u,v)$是不能安排在一起的,则连边$(u,v'),(v,u')$,然后就一个彻彻底底是一个板子了。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=3996000; int n; struct node{ int u,v,nex; }x[N<<1]; struct Node{ int st,end,t; }k[1001]; int cnt,head[2001]; void add(int u,int v){ // printf("u:%d v:%d ",u,v); x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++; } /*上 下+n*/ bool judge(int s1,int e1,int s2,int e2){ if(s1>s2) swap(s1,s2),swap(e1,e2); if(e1>s2) return 0; return 1; } int dfn[2001],low[2001],num,co[2001],col,sta[2001],tot; void tarjan(int f){ dfn[f]=low[f]=++num; sta[++tot]=f; for(int i=head[f];i!=-1;i=x[i].nex){ if(!dfn[x[i].v]){ tarjan(x[i].v); low[f]=min(low[f],low[x[i].v]); }else if(!co[x[i].v]) low[f]=min(low[f],dfn[x[i].v]); } if(low[f]==dfn[f]){ co[f]=++col; while(sta[tot]!=f){ co[sta[tot]]=col; tot--; }tot--; }return; } void print(int S){ printf("%02d:%02d",S/60,S%60); } void solve(){ memset(head,-1,sizeof(head)),cnt=0;memset(co,0,sizeof(co)),col=0,memset(dfn,0,sizeof(dfn)),memset(low,0,sizeof(low)),num=0; for(int i=1;i<=n;i++){ int h1=read(),min1=read(),h2=read(),min2=read(),t=read(); k[i].st=h1*60+min1,k[i].end=h2*60+min2; k[i].t=t; } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ /*i场上 j场上*/ int s1=k[i].st,e1=k[i].st+k[i].t;int s2=k[j].st,e2=k[j].st+k[j].t; if(!judge(s1,e1,s2,e2)) add(i,j+n),add(j,i+n); /*i场上 j场下*/ s1=k[i].st,e1=k[i].st+k[i].t;s2=k[j].end-k[j].t,e2=k[j].end; if(!judge(s1,e1,s2,e2)) add(i,j),add(j+n,i+n); /*i场下 j场上*/ s1=k[i].end-k[i].t,e1=k[i].end;s2=k[j].st,e2=k[j].st+k[j].t; if(!judge(s1,e1,s2,e2)) add(i+n,j+n),add(j,i); /*i场下 j场下*/ s1=k[i].end-k[i].t,e1=k[i].end;s2=k[j].end-k[j].t,e2=k[j].end; if(!judge(s1,e1,s2,e2)) add(i+n,j),add(j+n,i); } } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) if(co[i]==co[i+n]){printf("NO ");return;} printf("YES "); for(int i=1;i<=n;i++){ if(co[i]<co[i+n]){print(k[i].st);cout<<" ";print(k[i].st+k[i].t);} else {print(k[i].end-k[i].t);cout<<" ";print(k[i].end);} printf(" "); }return; } int main(){ while(scanf("%d",&n)!=EOF)solve(); }