poj 3683 Priest John's Busiest Day
题意:给出n个婚礼举行,每个婚礼有两个时间区间,必须选择其中一个,问能不能在每个婚礼都出现且时间不冲突,输出方案。
一看就是2-sat,但是这道题要输出方案。
http://blog.csdn.net/jarjingx/article/details/8521690
可以看看论文和博客,有详细讲解。
简单思路:
我们用tarjan缩完点之后把图中的边反向。
首先原图中的边是有传递性的,即选了A必须选B。
反过来之后,如果A到B有边,那么说明不选A的话一定不能选B,这个很好理解。
即不选的关系也是有传递性的。
那么我们在拓扑排序的时候,如果当前点没有标识为不选,那么就选择它,把它的对立点及所有对立点能访问到的点标记为不选。
这样一定能得到一组合法解。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define N 2005 7 #define M 2000005 8 using namespace std; 9 int n; 10 int tot,head[N],ver[M],nxt[M]; 11 void add(int a,int b) 12 { 13 tot++;nxt[tot]=head[b];head[b]=tot;ver[tot]=a;return ; 14 } 15 int tot2,head2[N],ver2[M],nxt2[M]; 16 void add2(int a,int b) 17 { 18 tot2++;nxt2[tot2]=head2[a];head2[a]=tot2;ver2[tot2]=b;return ; 19 } 20 int st[N],tim,in[N],dfn[N],low[N],top,be[N],cnt; 21 void dfs(int x) 22 { 23 dfn[x]=low[x]=++tim; 24 st[++top]=x; 25 in[x]=1; 26 for(int i=head[x];i;i=nxt[i]) 27 { 28 if(!dfn[ver[i]]) 29 { 30 dfs(ver[i]); 31 low[x]=min(low[x],low[ver[i]]); 32 } 33 else if(in[ver[i]]) 34 { 35 low[x]=min(low[x],dfn[ver[i]]); 36 } 37 } 38 if(low[x]==dfn[x]) 39 { 40 cnt++;int y; 41 do 42 { 43 y=st[top--]; 44 be[y]=cnt; 45 in[y]=0; 46 }while(y!=x); 47 } 48 } 49 struct node 50 { 51 int l,r; 52 }mr[N]; 53 bool check(int x,int y) 54 { 55 if(mr[x].r<=mr[y].l||mr[y].r<=mr[x].l)return 0; 56 return 1; 57 } 58 int rev[N],du[N]; 59 int c[N]; 60 void dffs(int x) 61 { 62 if(c[x])return ; 63 c[x]=-1; 64 for(int i=head2[x];i;i=nxt2[i])dffs(ver2[i]); 65 } 66 queue<int>q; 67 void tupu() 68 { 69 for(int i=1;i<=cnt;i++)if(!du[i])q.push(i); 70 while(!q.empty()) 71 { 72 int tmp=q.front();q.pop(); 73 if(c[tmp])continue; 74 c[tmp]=1;dffs(rev[tmp]); 75 for(int i=head2[tmp];i;i=nxt2[i]) 76 { 77 du[ver2[i]]--; 78 if(!du[ver2[i]])q.push(ver2[i]); 79 } 80 } 81 return ; 82 } 83 void pr(int x) 84 { 85 printf("%.2d:",x/60); 86 printf("%.2d ",x%60); 87 } 88 int main() 89 { 90 scanf("%d",&n); 91 char s1[10],s2[10];int tmp; 92 for(int i=1;i<=n;i++) 93 { 94 scanf("%s%s",s1,s2); 95 scanf("%d",&tmp); 96 mr[2*i].l=(s1[0]-'0')*10+s1[1]-'0'; 97 mr[2*i].l=mr[2*i].l*60+(s1[3]-'0')*10+s1[4]-'0'; 98 99 mr[2*i-1].r=(s2[0]-'0')*10+s2[1]-'0'; 100 mr[2*i-1].r=mr[2*i-1].r*60+(s2[3]-'0')*10+s2[4]-'0'; 101 102 mr[2*i].r=mr[2*i].l+tmp; 103 mr[2*i-1].l=mr[2*i-1].r-tmp; 104 } 105 for(int i=1;i<=n;i++) 106 { 107 for(int j=i+1;j<=n;j++) 108 { 109 if(check(2*i,2*j))add(2*i,2*j-1),add(2*j,2*i-1); 110 if(check(2*i,2*j-1))add(2*i,2*j),add(2*j-1,2*i-1); 111 if(check(2*i-1,2*j))add(2*i-1,2*j-1),add(2*j,2*i); 112 if(check(2*i-1,2*j-1))add(2*i-1,2*j),add(2*j-1,2*i); 113 } 114 } 115 for(int i=1;i<=2*n;i++)if(!dfn[i])dfs(i); 116 for(int i=1;i<=n;i++) 117 { 118 if(be[2*i]==be[2*i-1]) 119 { 120 puts("NO"); 121 return 0; 122 } 123 } 124 for(int i=1;i<=2*n;i++) 125 { 126 for(int j=head[i];j;j=nxt[j]) 127 { 128 if(be[i]!=be[ver[j]]) 129 { 130 add2(be[i],be[ver[j]]); 131 du[be[ver[j]]]++; 132 } 133 } 134 } 135 for(int i=1;i<=n;i++) 136 { 137 rev[be[i*2]]=be[2*i-1]; 138 rev[be[i*2-1]]=be[2*i]; 139 } 140 tupu(); 141 puts("YES"); 142 for(int i=1;i<=n;i++) 143 { 144 if(c[be[2*i]]==1) 145 { 146 pr(mr[2*i].l);pr(mr[2*i].r);puts(""); 147 } 148 else 149 { 150 pr(mr[2*i-1].l);pr(mr[2*i-1].r);puts(""); 151 } 152 } 153 return 0; 154 }