【題意】:平面上,一個圓,圓的邊上按順時針放著n個點。現在要連m條邊,比如a,b,那么a到b可以從圓的內部連接,也可以從圓的外部連接。給你的信息中,每個點最多只會連接的一條邊。問能不能連接這m條邊,使這些邊都不相交。

【題解】:題意可能剛開始不是很好理解,比如1和5連邊,2和6連邊,由于點是順序排列的,一畫圖就可以發現,這兩條邊必須一個從圓外面連,一個從內部連,否則就會相交。如果再加入3和7這條邊,那么就必須相交了。
              這樣,我們很容易把問題轉化為一個標準的2-sat問題,把每條邊看成2-sat中的點,i 表示這條邊從圓的內部連邊,i’ 表示從圓的外部連邊。
              如果某兩條邊 i  和 j 有矛盾關系(既只能一個從內部連邊,一個從外部連邊),那么我們可以這樣連邊: i -> j' , i' -> j, j -> i', j' -> i.
              最后判斷一下有無可行解即可。

【代碼】:
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "vector"
 5 using namespace std;
 6 #define maxn 1050
 7 int n, m;
 8 vector<int> vec[maxn];
 9 int s[maxn], top;
10 int belong[maxn], scc, dfn[maxn], low[maxn], Dindex;
11 bool instack[maxn];
12 struct Line {
13     int a, b;
14 }line[maxn];
15 
16 void dfs(int u) {
17     int v, size = vec[u].size();
18     dfn[u] = low[u] = ++Dindex;
19     instack[u] = true;
20     s[++top] = u;
21     for(int i = 0; i < size; i++) {
22         v = vec[u][i];
23         if(!dfn[v]) dfs(v), low[u] = min(low[u], low[v]);
24         else if(instack[v]) low[u] = min(low[u], dfn[v]);    
25     }
26     if(dfn[u] == low[u]) {
27         scc++;   
28         do {
29             v = s[top--];
30             instack[v] = false;
31             belong[v] = scc;
32         }while(v != u);
33     }
34 }
35 void tarjan() {
36     top = scc = Dindex = 0;
37     memset(dfn, 0sizeof(dfn));
38     memset(instack, 0sizeof(instack));
39     for (int u = 0; u < 2 * m; u++)
40         if(!dfn[u]) dfs(u);
41 }
42 
43 bool solvable() {
44     for(int i = 0; i < 2 * m; i += 2
45         if(belong[i] == belong[i^1]) return false;
46     return true;
47 }
48 
49 bool conflict(Line a, Line b) {
50     if(a.a > b.b || a.b < b.a || (a.a < b.a && a.b > b.b) || (a.a > b.a && a.b < b.b)) return false;
51     return true;
52 }
53 
54 void build() {
55     for(int i = 0; i < m; i++) {
56         for(int j = i + 1; j < m; j++) {
57             int u = 2 * i, v = 2 * j;
58             if(conflict(line[i], line[j])) {
59                 vec[u].push_back(v^1), vec[u^1].push_back(v);
60                 vec[v].push_back(u^1), vec[v^1].push_back(u);
61             }
62         }
63     }
64 }
65 
66 int main() {
67     for(int i = 0; i < maxn; i++) vec[i].clear();
68     scanf("%d%d"&n, &m);
69     for(int i = 0; i < m; i++) {
70         scanf("%d%d"&line[i].a, &line[i].b);
71         if(line[i].a > line[i].b) swap(line[i].a, line[i].b);
72     }
73     build();
74     tarjan();
75     if(solvable()) printf("panda is telling the truth\n");
76     else printf("the evil panda is lying again\n");
77     return 0;
78 }