HDU3715:Go Deeper【2-SAT】
——题目见描述吧……
——2-SAT,二分
——URL:http://acm.hdu.edu.cn/showproblem.php?pid=3715
——————————————————————————————————————————————————————————
福州现场赛的一道题。
看到x的取值为0,1,要有敏锐的嗅觉……
令p=a[i],q=b[i]
则P,Q分别是两个组,每个组包含两个元素{0,1}
c数组就是描述的这些元素的矛盾关系:
x[p]+x[q]!=0 即p组中的0和q组中的0不能同时存在
x[p]+x[q]!=2 即p组中的1和q组中的1不能同时存在
x[p]+x[q]!=1 即p组中的0和q组中的1不能同时存在 并且 组中的1和q组中的0不能同时存在
以上就是2-SAT问题了。
由于要求的事DEP
所以需要二分dep,然后用2-SAT判断是否可行。
View Code
1 #include<stdio.h>
2 #include<memory.h>
3 #define N 205
4 #define M 10005
5 #define E 60005
6 int head[N * 2], id[N*2],pre[N*2],low[N*2],s[N*2],nxt[E],ev[E],a[M],b[M],c[M];
7 int stop, cnt, scnt, n, m, num;
8 void readin()
9 {
10 int i;
11 scanf("%d%d", &n, &m);
12 for (i = 0; i < m; i++)
13 scanf("%d%d%d", &a[i], &b[i], &c[i]);
14 }
15 void tarjan(int v, int n)
16 {
17 int pv, t, minc = low[v] = pre[v] = cnt++;
18 s[stop++] = v;
19 for (pv = head[v]; pv != -1; pv = nxt[pv])
20 {
21 if (-1 == pre[ev[pv]])
22 tarjan(ev[pv], n);
23 if (low[ev[pv]] < minc)
24 minc = low[ev[pv]];
25 }
26 if (minc < low[v])
27 {
28 low[v] = minc;
29 return;
30 }
31 do
32 {
33 id[t = s[--stop]] = scnt;
34 low[t] = n;
35 } while (t != v);
36 ++scnt;
37 }
38 void addedge(int u, int v)
39 {
40 nxt[++num] = head[u];
41 head[u] = num;
42 ev[num] = v;
43 }
44 void solve()
45 {
46 int l, r, mid, ans, i;
47 bool flag;
48 l = 0;
49 r = m;
50 ans = 0;
51 while (l <= r)
52 {
53 mid = (l + r) >> 1;
54 memset(head, -1, sizeof(head));
55 num = -1;
56 for (i = 0; i < mid; i++)
57 {
58 switch (c[i])
59 {
60 case 0:
61 addedge(2 * a[i], 2 * b[i] + 1);
62 addedge(2 * b[i], 2 * a[i] + 1);
63 break;
64 case 1:
65 addedge(2 * a[i], 2 * b[i]);
66 addedge(2 * a[i] + 1, 2 * b[i] + 1);
67 addedge(2 * b[i], 2 * a[i]);
68 addedge(2 * b[i] + 1, 2 * a[i] + 1);
69 break;
70 case 2:
71 addedge(2 * a[i] + 1, 2 * b[i]);
72 addedge(2 * b[i] + 1, 2 * a[i]);
73 break;
74 }
75 }
76 stop = cnt = scnt = 0;
77 memset(pre, -1, sizeof(pre));
78 for (i = 0; i < n * 2; i++)
79 if (pre[i] == -1)
80 tarjan(i, n * 2);
81 flag = true;
82 for (i = 0; i < n; i++)
83 if (id[i * 2] == id[i * 2 + 1])
84 {
85 flag = false;
86 break;
87 }
88 if (flag)
89 {
90 ans = mid;
91 l = mid + 1;
92 }
93 else
94 r = mid - 1;
95 }
96 printf("%d\n", ans);
97 }
98 int main()
99 {
100 int cas;
101 scanf("%d", &cas);
102 while (cas--)
103 {
104 readin();
105 solve();
106 }
107 return 0;
108 }