思路:把每一条线段当做点,则有“内”、“外”两种取值,然后在冲突的线段之间连边,判断是否有解即可。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int N = 500; 8 const int M = 1000000; 9 int head[N * 2]; 10 int s[N * 2]; 11 bool mark[N * 2]; 12 int n, e, c; 13 14 struct Edge 15 { 16 int v, next; 17 } edge[M]; 18 19 void addEdge( int u, int v ) 20 { 21 edge[e].v = v; 22 edge[e].next = head[u]; 23 head[u] = e++; 24 } 25 26 void init() 27 { 28 e = 0; 29 memset( head, -1, sizeof(head) ); 30 memset( mark, false, sizeof(mark) ); 31 } 32 33 bool dfs( int u ) 34 { 35 if ( mark[u ^ 1] ) return false; 36 if ( mark[u] ) return true; 37 mark[u] = true; 38 s[c++] = u; 39 for ( int i = head[u]; i != -1; i = edge[i].next ) 40 { 41 int v = edge[i].v; 42 if ( !dfs(v) ) return false; 43 } 44 return true; 45 } 46 47 bool solve() 48 { 49 for ( int i = 0; i < 2 * n; i += 2 ) 50 { 51 if ( !mark[i] && !mark[i + 1] ) 52 { 53 c = 0; 54 if ( !dfs(i) ) 55 { 56 while ( c ) 57 { 58 c--; 59 mark[s[c]] = false; 60 } 61 if ( !dfs( i + 1 ) ) return false; 62 } 63 } 64 } 65 return true; 66 } 67 68 struct T 69 { 70 int x, y; 71 } t[N]; 72 73 int main () 74 { 75 scanf("%d%d", &n, &n); 76 init(); 77 for ( int i = 0; i < n; i++ ) 78 { 79 scanf("%d%d", &t[i].x, &t[i].y); 80 if ( t[i].x > t[i].y ) swap( t[i].x, t[i].y ); 81 for ( int j = 0; j < i; j++ ) 82 { 83 if ( ( t[i].x < t[j].x && t[i].y < t[j].y && t[i].y > t[j].x ) 84 || ( t[i].x > t[j].x && t[i].y > t[j].y && t[i].x < t[j].y ) ) 85 { 86 int li = i << 1, ri = li | 1; 87 int lj = j << 1, rj = lj | 1; 88 addEdge( li, rj ); 89 addEdge( ri, lj ); 90 addEdge( lj, ri ); 91 addEdge( rj, li ); 92 } 93 } 94 } 95 if ( solve() ) 96 { 97 puts("panda is telling the truth..."); 98 } 99 else 100 { 101 puts("the evil panda is lying again"); 102 } 103 return 0; 104 }