POJ3683 Falsita

http://poj.org/problem?id=3683

思路:2-SAT,输出任意一组方案,O(m+n)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 int first[2000005],next[2000005],tot,go[2000005];
  7 int First[2000005],Next[2000005],Tot,Go[2000005];
  8 int b[200005],a[200005],n,ru[200005],low[200005],dfn[200005];
  9 int op[2000005],belong[200005],instack[200005],vis[200005],st[200005],c[200005],col[200005],sz,num,top;
 10 int read(){
 11     int t=0,f=1;char ch=getchar();
 12     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();}
 13     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
 14     return t*f;
 15 }
 16 void insert(int x,int y){
 17     tot++;
 18     go[tot]=y;
 19     next[tot]=first[x];
 20     first[x]=tot;
 21 }
 22 void Insert(int x,int y){
 23     Tot++;
 24     Go[Tot]=y;
 25     Next[Tot]=First[x];
 26     First[x]=Tot;
 27 }
 28 bool jud(int x,int y){
 29     if (b[x]<=a[y]||a[x]>=b[y]) return 0;
 30     else return 1;
 31 }
 32 void build(){
 33     for (int i=1;i<=n;i++)
 34      for (int j=i+1;j<=n;j++){
 35         if (jud(i*2-1,j*2)){
 36             insert(i*2-1,j*2-1);
 37             insert(j*2,i*2);
 38         }
 39         if (jud(i*2-1,j*2-1)){
 40             insert(i*2-1,j*2);
 41             insert(j*2-1,i*2);
 42         }
 43         if (jud(i*2,j*2)){
 44             insert(i*2,j*2-1);
 45             insert(j*2,i*2-1);
 46         }
 47         if (jud(i*2,j*2-1)){
 48             insert(i*2,j*2);
 49             insert(j*2-1,i*2-1);
 50         }
 51      }
 52 }
 53 void init(){
 54     n=read();
 55     for (int i=1;i<=n;i++){
 56         a[i*2]=read();
 57         a[i*2]=a[i*2]*60+read();
 58         b[i*2-1]=read();
 59         b[i*2-1]=b[i*2-1]*60+read();
 60         int x=read();
 61         b[i*2]=a[i*2]+x;
 62         a[i*2-1]=b[i*2-1]-x;
 63     }
 64 }
 65 void tarjan(int x){
 66     low[x]=dfn[x]=++sz;
 67     instack[x]=vis[x]=1;st[++top]=x;
 68     for (int i=first[x];i;i=next[i]){
 69         int pur=go[i];
 70         if (!vis[pur]){
 71             tarjan(pur);
 72             low[x]=std::min(low[x],low[pur]);
 73         }else if (instack[pur]){
 74             low[x]=std::min(low[x],dfn[pur]);
 75         }
 76     }
 77     if (low[x]==dfn[x]){
 78         num++;
 79         while (st[top]!=x){
 80             instack[st[top]]=0;
 81             belong[st[top]]=num;
 82             top--;
 83         }
 84             instack[st[top]]=0;
 85             belong[st[top]]=num;
 86             top--;
 87     }
 88 }
 89 void Tarjan(){
 90     for (int i=1;i<=2*n;i++)
 91      if (!vis[i]) tarjan(i);
 92 }
 93 bool judge(){
 94     for (int i=1;i<=n;i++)
 95      if (belong[i*2]==belong[i*2-1]) {
 96             puts("NO");
 97             return 1;
 98      }
 99     puts("YES");
100     return 0;
101 }
102 void dfs(int x){
103     if (col[x]) return ;col[x]=-1;
104     for (int i=First[x];i;i=Next[i]){
105         int pur=Go[i];
106         dfs(pur);
107     }
108 }
109 void topsort(){
110     int t=0;
111     for (int i=1;i<=num;i++)
112      if (!ru[i]) c[++t]=i;
113     while (t){
114         int now=c[t--];
115         if (col[now]) continue;col[now]=1;
116         dfs(op[now]);
117         for (int i=First[now];i;i=Next[i]){
118             int pur=Go[i];
119             ru[pur]--;
120             if (ru[pur]==0) c[++t]=pur;
121         }
122     }
123 }
124 void rebuild(){
125     for (int i=1;i<=2*n;i++)
126      for (int j=first[i];j;j=next[j]){
127             int pur=go[j];
128             if (belong[pur]==belong[i]) continue;
129             ru[belong[i]]++;
130             Insert(belong[pur],belong[i]);;
131      }
132     for (int i=1;i<=2*n;i++)
133      op[belong[i*2]]=belong[i*2-1],op[belong[i*2-1]]=belong[i*2];
134 }
135 void print(int x){
136     printf("%.2d:",x/60);
137     printf("%.2d ",x%60);
138 }
139 void Output(){
140     for (int i=1;i<=n;i++)
141      if (col[belong[i*2]]==1){
142             print(a[i*2]);print(b[i*2]);puts("");
143      }else{
144             print(a[i*2-1]);print(b[i*2-1]);puts("");
145      }
146 }
147 int main(){
148     init();
149     build();
150     Tarjan();
151     if (judge()) return 0;
152     rebuild();
153     topsort();
154     Output();
155 }

为什么我会犯用错数组这种错误。。

时间: 2024-08-04 10:08:47

POJ3683 Falsita的相关文章

POJ-3683 Priest John&#39;s Busiest Day

图论中的2-SAT.模板题. #include <cstdio> #include <cstdlib> #include <algorithm> #include <cctype> #include <cstring> #include <iostream> using namespace std; #define rep(i, l, r) for(int i=l; i<=r; i++) #define travel(x) fo

Poj3683(2-set

poj3683 题目:有若干个活动可以选择两个时间段中的一个举行,询问使得所有活动不冲突的分配方案. 思路:2set裸题,sset需要先进行强联通分量分解,然后需要进行一次拓扑排序,但是如果强联通分量分解时使用两次dfs的方式,那么可以省去这一步. /* * @author: Cwind */ ///#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <m

2-sat问题,输出方案,几种方法(赵爽的论文染色解法+其完全改进版)浅析 / POJ3683

本文原创于  2014-02-12 09:26. 今复习之用,有新体会,故重新编辑. 2014-02-12 09:26: 2-sat之第二斩!昨天看了半天论文(赵爽的和俉昱的),终于看明白了!好激动有木有!终于理解了赵爽的每一句话!并且用了200+行代码实现,A了!具体过程我是敲了帮天的代码啊!!!不容易啊!步骤如下: 把相关问题编号为01 23 45....,(每个编号为一个命题)奇数为取,偶数不取,那么相邻俩个互逆,于是根据具体情况(check)一下,建立图,tarjan判断有无解,然后顺便

poj3683 Priest John&#39;s Busiest Day

不用topsort的,我也不知道为啥. #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Node{ int fro, too; }nd[2005]; struct Edge{ int too, nxt, val; }edge[4000005]; int uu, vv, ww, n, hea[2005], cnt, dfn[2005], loo[200

Poj3683:Priest John&#39;s Busiest Day

题意 n对夫妻要结婚,第i对夫妻结婚的婚礼持续时间为[Si, Ti],他们会举行一个仪式,仪式时间为Di,这个仪式只能举行在开头或者结尾举行,要么[Si, Si+Di],要么[Ti-Di, Ti],然而举行仪式的牧师只有一个,问牧师能否举行完所有仪式 按输入顺序输出方案 手动翻译 Sol \(2-SAT\)输出一组可行解 这个很烦 \(Tarjan\)缩点成\(DAG\)后再拓扑排序+染色 只传递不选的标记 # include <iostream> # include <stdio.h&

poj3683 2-SAT 同上一道

Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10151   Accepted: 3475   Special Judge Description John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old l

bzoj3683 Falsita

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3683 [题解] 首先我们需要化简式子 $ans = P / S$ 其中,$S = (sz_x^2 - 1 - \sum_{y = son[x]} sz_y^2) / 2$ 这个显然可以预处理. 然后我们经过简单推导可以得出$ P = w_x * (sz_x - 1) + \sum_{y = son[x]} (sz_x - sz_y) * sum_y$ 经过如下化简,可以得到 $ P = w

poj3683

题解: 2-sat 然后不用拓扑 直接强连通的逆序就可以了 代码: #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=2005; int flag[N],ans,l,n; int ne[N*N],fi[N],a[N],b[N],zz[N*N],num,t,zhan[N],dfn[N],low[N],an

【小结】2-sat

2?sat 小结 2?sat解决的是可满足性问题,并且每个合取范式中的文字个数不多于2个. 形式为: (a∨?b)∧(?c∨?d)∧(?a∨d)? 将所有a∨b改成(?a?b)∧(?b?a) 建边,每个变量a对应两个点a和a+n 如果存在cmp[a]==cmp[a+n]不成立,否则成立.且如果cmp[a]>cmp[a+n],令a=true,否则令a=false即为原式的一组解. #include <cstdio> #include <iostream> #include &l