zoukankan      html  css  js  c++  java
  • POJ 2SAT 六题

    POJ 3207 - Ikki's Story IV - Panda's Trick
    http://acm.pku.edu.cn/JudgeOnline/problem?id=3207
    POJ 3678 - Katu Puzzle
    http://acm.pku.edu.cn/JudgeOnline/problem?id=3678
    POJ 2723 - Get Luffy Out
    http://acm.pku.edu.cn/JudgeOnline/problem?id=2723
    POJ 3683 - Priest John's Busiest Day
    http://acm.pku.edu.cn/JudgeOnline/problem?id=3683
    POJ 2749 - Building roads
    http://acm.pku.edu.cn/JudgeOnline/problem?id=2749
    POJ 3648- Wedding
    http://acm.pku.edu.cn/JudgeOnline/problem?id=3648

    POJ 3207 Ikki's Story IV - Panda's Trick

    题意:一个圆的边上有n个编号连续的点,要用m条线把这些点连起来,并且线不可以相交。(这些线可以从圆内连也可以从圆外绕过去),问是否有符合条件的m条边。

    思路:把一条边看成一个点,如果 i 线和 j 线相交则表示i j 冲突则连接 i -> ~j, j -> ~i。因为这里i j都是必然出现的,所以要连成无向图。

    渣代码:

    View Code
      1 #include <iostream>
    2 #include <cstring>
    3 #include <cstdio>
    4 #include <vector>
    5
    6 using namespace std;
    7
    8 const int N = 1010;
    9 const int M = 5000005;
    10
    11 struct node {
    12 int to;
    13 int next;
    14 } g[M];
    15
    16 int head[N], scc[N];
    17 int dfn[N], low[N];
    18 int a[2][N], s[N];
    19 int t, ind, cnt, top;
    20 bool vis[N];
    21
    22 void swap(int *a, int *b) {
    23 int *t;
    24 t = a; a = b; b = t;
    25 }
    26
    27 void init() {
    28 for(int i = 0; i < N; i++) {
    29 head[i] = scc[i] = dfn[i] = low[i] = vis[i] = 0;
    30 }
    31 t = 1; ind = cnt = top = 0;
    32 }
    33
    34 void add(int u, int v) {
    35 g[t].to = v; g[t].next = head[u]; head[u] = t++;
    36 }
    37
    38 void dfs(int u) {
    39 int v, i;
    40 dfn[u] = low[u] = ++ind;
    41 s[++top] = u; vis[u] = true;
    42 for(i = head[u]; i; i = g[i].next) {
    43 v = g[i].to;
    44 if(!dfn[v]) {
    45 dfs(v);
    46 low[u] = min(low[u], low[v]);
    47 } else if(vis[v]) {
    48 low[u] = min(low[u], dfn[v]);
    49 }
    50 }
    51 if(dfn[u] == low[u]) {
    52 cnt++;
    53 do {
    54 v = s[top--];
    55 //printf("%d %d\n", v, cnt);
    56 scc[v] = cnt;
    57 vis[v] = false;
    58 } while(v != u);
    59 }
    60 }
    61
    62 void tarjan(int n) {
    63 for(int i = 0; i < n; i++) {
    64 if(!dfn[i]) dfs(i);
    65 }
    66 }
    67
    68 bool solve(int n) {
    69 tarjan(n);
    70 for(int i = 0; i < n; i += 2) {
    71 if(scc[i] == scc[i+1]) return false;
    72 }
    73 return true;
    74 }
    75
    76 int main() {
    77 //freopen("data.in", "r", stdin);
    78
    79 int n, m;
    80 int i, j;
    81 while(~scanf("%d%d", &n, &m)) {
    82 init();
    83 for(i = 0; i < m; i++) {
    84 scanf("%d%d", &a[0][i], &a[1][i]);
    85 if(a[0][i] > a[1][i]) swap(a[0][i], a[1][i]);
    86 //printf("%d %d\n", a[0][i], a[1][i]);
    87 for(j = 0; j < i; j++) {
    88 if((a[0][j] < a[0][i] && a[1][j] > a[0][i] && a[1][j] < a[1][i])
    89 || (a[0][j] > a[0][i] && a[0][j] < a[1][i] && a[1][j] > a[1][i])) {
    90 add((i<<1), (j<<1) + 1); add((j<<1) + 1, (i<<1));
    91 //printf("%d %d %d %d\n", (i<<1), (j<<1) + 1, (j<<1) + 1, (i<<1));
    92 add((j<<1), (i<<1) + 1); add((i<<1) + 1, (j<<1));
    93 //printf("%d %d %d %d\n", (j<<1), (i<<1) + 1, (i<<1) + 1, (j<<1));
    94 }
    95 }
    96 }
    97 if(solve(m<<1)) cout << "panda is telling the truth..." << endl;
    98 else cout << "the evil panda is lying again" << endl;
    99 }
    100 return 0;
    101 }



     

    POJ 3678 解题报告:http://www.cnblogs.com/vongang/archive/2012/02/15/2352246.html

     

    POJ 2723 Get Luffy Out

    题意:给m个门,每个门上有两把锁(总共2N种锁),打开其中一把就可以把们打开。现在有2N把钥匙,组成N个钥匙对,问最多能开几扇门(开完1号才能开2号,依次类推)

    思路:设x, y组成的钥匙对,可知 x XOR y = 1;所以 x -> ~y, y -> ~x;

    每扇门上的锁x, y,可知x | y = 1; 所以~x, 和~y矛盾,所以 ~x -> y, ~y -> x;

    然后二分建图,求出能开的门数。

    ps:g++能过,c++ wa, 纠结。

    渣代码:

    View Code
      1 #include <iostream>
    2 #include <cstring>
    3 #include <cstdio>
    4
    5 using namespace std;
    6
    7 const int N = 5000;
    8 const int M = 60000;
    9
    10 struct node {
    11 int to;
    12 int next;
    13 } g[M];
    14
    15 int head[N], scc[N];
    16 int dfn[N], low[N], s[M];
    17 int a[2][N], b[2][N];
    18 int t, top, n, ind, cnt;
    19
    20 bool vis[N];
    21
    22 void init() {
    23 for(int i = 0; i <= N; i++) {
    24 head[i] = low[i] = dfn[i] = vis[i] = 0;
    25 }
    26 t = 1; ind = top = cnt = 0;
    27 }
    28
    29 void add(int u, int v) {
    30 g[t].to = v; g[t].next = head[u]; head[u] = t++;
    31 }
    32
    33 void dfs(int u) {
    34 int v, i;
    35 dfn[u] = low[u] = ++ind;
    36 s[top++] = u; vis[u] = true;
    37 for(i = head[u]; i; i = g[i].next) {
    38 v = g[i].to;
    39 if(!dfn[v]) {
    40 dfs(v);
    41 low[u] = min(low[u], low[v]);
    42 } else if(vis[v]) {
    43 low[u] = min(low[u], dfn[v]);
    44 }
    45 }
    46 if(low[u] == dfn[u]) {
    47 cnt++;
    48 do {
    49 v = s[--top];
    50 scc[v] = cnt;
    51 vis[v] = false;
    52 } while(u != v);
    53 }
    54 }
    55
    56 void tarjan() {
    57 for(int i = 0; i < n<<2; i++) {
    58 if(!dfn[i]) dfs(i);
    59 }
    60 }
    61
    62 void creat_g(int m) {
    63 int i;
    64 for(i = 0; i < n; i++) {
    65 add((a[0][i]<<1), (a[1][i]<<1) + 1);
    66 add((a[1][i]<<1), (a[0][i]<<1) + 1);
    67 }
    68 for(i = 0; i < m; i++) {
    69 add((b[0][i]<<1) + 1, (b[1][i]<<1));
    70 add((b[1][i]<<1) + 1, (b[0][i]<<1));
    71 }
    72 }
    73
    74 bool solve() {
    75 tarjan();
    76 for(int i = 0; i < n<<2; i += 2) {
    77 if(scc[i] == scc[i+1]) return false;
    78 }
    79 return true;
    80 }
    81
    82 int main() {
    83 //freopen("data.in", "r", stdin);
    84
    85 int m, i;
    86 while(~scanf("%d%d", &n, &m)) {
    87 if(!n && !m) break;
    88 memset(a, 0, sizeof(a));
    89 memset(b, 0, sizeof(b));
    90
    91 for(i = 0; i < n; i++) {
    92 scanf("%d%d", &a[0][i], &a[1][i]);
    93 }
    94 for(i = 0; i < m; i++) {
    95 scanf("%d%d", &b[0][i], &b[1][i]);
    96 }
    97
    98 int l = 0, r = m, mid;
    99 while(l <= r) {
    100 mid = (l + r) >> 1;
    101 init();
    102 creat_g(mid);
    103 if(solve()) l = mid + 1;
    104 else r = mid - 1;
    105 //printf("%d %d %d\n", l, r, mid);
    106 }
    107 printf("%d\n", r);
    108 }
    109 return 0;
    110 }

     

    POJ 3683 - Priest John's Busiest Day

    题意很清楚。关键是输出一组可行解。

    思路:把开始时间短,结束时间段看成两个对立的点,建图方法同POJ 3207。输出时根据赵爽的论文 + 网上的输出可行解模板。。。终于A了。

    输出可行解部分的思路:

    按缩点以后的有向无环图的边反向建图G。以G上所有入度为0的点为始点,将其染成红色,和这些点对立的点染成绿色,然后按图进行拓扑排序。知道所有的点都染色。

    关键部分代码:

    View Code
     1     for(i = 0; i < t; i++) {
    2 if(scc[g[i].to] != scc[g[i].from]) { //反向建图
    3 addG(scc[g[i].to], scc[g[i].from]);
    4 //printf("%d %d %d %d\n", g[i].to, g[i].from, scc[g[i].to], scc[g[i].from]);
    5 indeg[scc[g[i].from]]++;
    6 }
    7 }
    8 for(i = 1; i <= cnt; i++) {
    9 if(indeg[i] == 0) q.push(i); //入度为0的点入队列
    10 }
    11
    12 while(!q.empty()) { //进行拓扑排序
    13 u = q.front();
    14 if(col[u] == 0) { //未染色的入度为0的点染成红色,其对立点染成绿色
    15 col[u] = 1;
    16 col[opp[u]] = -1;
    17 }
    18 q.pop();
    19 for(i = head[u]; i; i = G[i].next) {
    20 v = G[i].to;
    21 indeg[v]--;
    22 if(indeg[v] == 0) {
    23 q.push(v);
    24 }
    25 }
    26 }

     

    完整版:

    View Code
      1 #include <iostream>
    2 #include <cstring>
    3 #include <cstdio>
    4 #include <queue>
    5
    6 using namespace std;
    7
    8 const int N = 2012;
    9 const int M = 2000000;
    10
    11 struct node {
    12 int from;
    13 int to;
    14 int next;
    15 } g[M], G[M];
    16
    17 struct timm {
    18 int l;
    19 int r;
    20 } tim[N];
    21
    22 int head[N], scc[N];
    23 int dfn[N], low[N];
    24 int s[N], col[N];
    25 int indeg[N], opp[N];
    26 bool vis[N], ans[N];
    27
    28 int t, tg, ind, cnt, top;
    29
    30 void init() {
    31 for(int i = 0; i < N; i++) {
    32 col[i] = indeg[i] = ans[i] = 0;
    33 head[i] = scc[i] = dfn[i] = low[i] = vis[i] = 0;
    34 }
    35 memset(tim, 0, sizeof(tim));
    36 tg = t = 1; ind = cnt = top = 0;
    37 }
    38
    39 void add(int u, int v) {
    40 g[t].from = u; g[t].to = v; g[t].next = head[u]; head[u] = t++;
    41 }
    42
    43 void addG(int u, int v) {
    44 G[tg].from = u; G[tg].to = v; G[tg].next = head[u]; head[u] = tg++;
    45 }
    46
    47 void dfs(int u) {
    48 int v, i;
    49 dfn[u] = low[u] = ++ind;
    50 s[top++] = u; vis[u] = true;
    51 for(i = head[u]; i; i = g[i].next) {
    52 v = g[i].to;
    53 if(!dfn[v]) {
    54 dfs(v);
    55 low[u] = min(low[u], low[v]);
    56 } else if(vis[v]) {
    57 low[u] = min(low[u], dfn[v]);
    58 }
    59 }
    60 if(dfn[u] == low[u]) {
    61 cnt++;
    62 do {
    63 v = s[--top];
    64 scc[v] = cnt;
    65 vis[v] = false;
    66 } while(u != v);
    67 }
    68 }
    69
    70 void tarjan(int n) {
    71 for(int i = 0; i < n; i++) {
    72 if(!dfn[i]) dfs(i);
    73 }
    74 }
    75
    76 bool sat(int n) {
    77 tarjan(n);
    78 for(int i = 0; i < n; i += 2) {
    79 if(scc[i] == scc[i+1]) return false;
    80 opp[scc[i]] = scc[i+1];
    81 opp[scc[i+1]] = scc[i];
    82 }
    83 return true;
    84 }
    85
    86 void topo(int n) {
    87 queue<int> q;
    88 memset(col, 0, sizeof(col));
    89 memset(head, 0, sizeof(head));
    90 int i, u, v;
    91 for(i = 0; i < t; i++) {
    92 if(scc[g[i].to] != scc[g[i].from]) {
    93 addG(scc[g[i].to], scc[g[i].from]);
    94 //printf("%d %d %d %d\n", g[i].to, g[i].from, scc[g[i].to], scc[g[i].from]);
    95 indeg[scc[g[i].from]]++;
    96 }
    97 }
    98 for(i = 1; i <= cnt; i++) {
    99 if(indeg[i] == 0) q.push(i);
    100 }
    101
    102 while(!q.empty()) {
    103 u = q.front();
    104 if(col[u] == 0) {
    105 col[u] = 1;
    106 col[opp[u]] = -1;
    107 }
    108 q.pop();
    109 for(i = head[u]; i; i = G[i].next) {
    110 v = G[i].to;
    111 indeg[v]--;
    112 if(indeg[v] == 0) {
    113 q.push(v);
    114 }
    115 }
    116 }
    117 for(i = 0; i < n<<1; i += 2) {
    118 if(col[scc[i]] == 1) {
    119 //printf("%d\n", i);
    120 printf("%02d:%02d %02d:%02d\n", tim[i].l/60, tim[i].l%60, tim[i].r/60, tim[i].r%60);
    121 } else {
    122 //printf("%d\n", i+1);
    123 printf("%02d:%02d %02d:%02d\n", tim[i + 1].l/60, tim[i + 1].l%60, tim[i + 1].r/60, tim[i + 1].r%60);
    124 }
    125 }
    126 }
    127
    128 int main() {
    129 //freopen("data.in", "r", stdin);
    130
    131 int n, i, j;
    132 int x, y, a, b, d;
    133 while(~scanf("%d", &n)) {
    134 init();
    135
    136 for(i = 0; i < n; i++) {
    137 scanf("%d:%d %d:%d %d", &x, &y, &a, &b, &d);
    138 x = x*60 + y; a = a*60 + b;
    139 tim[i<<1].l = x;
    140 tim[i<<1].r = x + d;
    141 tim[(i<<1) + 1].l = a - d;
    142 tim[(i<<1) + 1].r = a;
    143 //printf("%d %d %d %d\n", x, x + d, a - d, a);
    144 }
    145 for(i = 0; i < 2*n; i++) {
    146 for(j = 0; j < 2*n; j++) {
    147 if(i == j || (i^1) == j) continue;
    148 if(tim[i].l < tim[j].r && tim[j].l < tim[i].r) {
    149 //printf("~~%d %d\n", i, j^1);
    150 add(i, j^1);
    151 }
    152 }
    153 }
    154 if(!sat(n<<1)) {cout << "NO" << endl; continue;}
    155 cout << "YES" << endl;
    156 topo(n);
    157 }
    158 return 0;
    159 }

     

    POJ 3648- Wedding

    题意:一对新人举行婚礼,并邀请很多夫妇参加。其中有一个长桌子,桌子两边可以坐人。新娘因为头发做的太牛叉了,把眼睛都遮住了,所以只能看到桌子对面坐的人,不能看到自己这一面的。同时,新娘如果看到对面做的人里边有夫妇俩会不高兴的。现在知道里边有一些人通奸(也可能是搞基),新娘看到对面的人里边有两个通奸的也会不高兴。现在为了使新娘高兴,请你安排坐次。

    思路:奇数表示男士,偶数表示女士。新娘是0号,新郎是1号。连续的两个奇偶数表示夫妇俩。然后按照矛盾关系建图。然后染色求出新郎那一边的就座情况(注意:需要加一条0 -> 1的边。这样如果选到新娘就一定会选到新郎,又因为新郎和新娘不在同一边,所以可以排除掉这种情况)

    渣代码:

    View Code
      1 #include <iostream>
    2 #include <cstdio>
    3 #include <cstring>
    4 #include <queue>
    5
    6 using namespace std;
    7
    8 const int N = 1024;
    9 const int M = 100000;
    10
    11 struct node {
    12 int from;
    13 int to;
    14 int next;
    15 } g[M], G[M];
    16
    17 int head[N], scc[N];
    18 int dfn[N], low[N];
    19 int col[N], indeg[N];
    20 int opp[N], s[N];
    21 int t, T, top, cnt, ind;
    22 bool vis[N];
    23
    24 void init() {
    25 for(int i = 0; i < N; i++) {
    26 opp[i] = head[i] = col[i] = indeg[i] = 0;
    27 s[i] = dfn[i] = low[i] = scc[i] = vis[i] = 0;
    28 }
    29 t = T = 1; ind = cnt = top = 0;
    30 }
    31
    32 void add(int u, int v) {
    33 g[t].from = u; g[t].to = v; g[t].next = head[u]; head[u] = t++;
    34 }
    35
    36 void _add(int u, int v) {
    37 G[T].from = u; G[T].to = v; G[T].next = head[u]; head[u] = T++;
    38 }
    39
    40 void tarjan(int u) {
    41 int v, i;
    42 dfn[u] = low[u] = ++ind;
    43 vis[u] = true; s[top++] = u;
    44 for(i = head[u]; i; i = g[i].next) {
    45 v = g[i].to;
    46 if(!dfn[v]) {
    47 tarjan(v);
    48 low[u] = min(low[u], low[v]);
    49 } else if(vis[v]) {
    50 low[u] = min(low[u], dfn[v]);
    51 }
    52 }
    53 if(dfn[u] == low[u]) {
    54 cnt++;
    55 do {
    56 v = s[--top];
    57 //printf("%d %d\n", v, cnt);
    58 scc[v] = cnt;
    59 vis[v] = false;
    60 } while(v != u);
    61 }
    62 }
    63
    64 bool solve(int n) {
    65 int i;
    66 for(i = 0; i < (n<<1); i++) {
    67 if(!dfn[i]) tarjan(i);
    68 }
    69 for(i = 0; i < (n<<1); i += 2) {
    70 if(scc[i] == scc[i+1]) return false;
    71 opp[scc[i]] = scc[i+1];
    72 opp[scc[i+1]] = scc[i];
    73 }
    74 return true;
    75 }
    76
    77 void topo_sat() {
    78 queue<int> q;
    79 int i, u, v;
    80 memset(head, 0, sizeof(head));
    81 for(i = 0; i < t; i++) {
    82 if(scc[g[i].to] != scc[g[i].from]) {
    83 //printf("%d %d\n", g[i].from, g[i].to);
    84 _add(scc[g[i].to], scc[g[i].from]);
    85 //printf("%d %d\n", scc[g[i].to], scc[g[i].from]);
    86 indeg[scc[g[i].from]] ++;
    87 }
    88 }
    89 for(i = 1; i <= cnt; i++) {
    90 if(indeg[i] == 0) q.push(i);
    91 }
    92 while(!q.empty()) {
    93 u = q.front(); q.pop();
    94 if(col[u] == 0) {
    95 col[u] = 1;
    96 col[opp[u]] = -1;
    97 }
    98 for(i = head[u]; i; i = G[i].next) {
    99 v = G[i].to;
    100 if(--indeg[v] == 0) q.push(v);
    101 }
    102 }
    103 }
    104
    105 int main() {
    106 //freopen("data.in", "r", stdin);
    107
    108 int n, m;
    109 int x, y, i;
    110 char c, d;
    111 while(scanf("%d%d", &n, &m), n||m) {
    112 init();
    113 while(m--) {
    114 scanf("%d%c%d%c", &x, &c, &y, &d);
    115
    116 if(c == 'w') x *= 2;
    117 else x = x*2 + 1;
    118 if(d == 'w') y *= 2;
    119 else y = y*2 + 1;
    120 if(x != (y^1)) {
    121 add(x, y^1);
    122 //printf("%d %d\n", x, y^1);
    123 add(y, x^1);
    124 //printf("%d %d\n", y, x^1);
    125 }
    126 }
    127 add(0, 1);
    128 if(!solve(n)) {cout << "bad luck" << endl; continue;}
    129 topo_sat(); x = 0;
    130 for(i = 0; i < n<<1; i++) {
    131 if(col[scc[i]] == 1 && i != 1) {
    132 if(!x) x = 1;
    133 else printf(" ");
    134 printf("%d", i/2);
    135 if(i%2 == 0) putchar('h'); //因为得到的是新郎一边的就坐情况,所以调换一下夫妇的符号就是新娘一边的。
    136 else putchar('w');
    137 }
    138 }
    139 cout << endl;
    140 }
    141 return 0;
    142 }
    143
    144 //ps: 题目要的是一组可行解。有很多种情况

     

    POJ 2749 - Building roads

    思路:先按hate关系和friend关系建图,i j为hate关系,则i -> ~j, j -> ~i, ~j -> i, ~i -> j; friend类似。此外,二分时加一个限制然后加边。

    设dis1[i]是点i到s1的距离,dis2[i]是点i到s2的距离。i 表示点连s1, ~i表示点连s2.

    dis1[i] + dis1[j] > limite   i -> ~j, j -> ~i;

    dis2[i] + dis2[j] > limite  ~i -> j, ~j -> i;

    dis1[i] + dis2[j] + D > limite   i -> j, ~j -> ~i

    dis2[i] + dis1[j] + D > limite  ~i - > ~j, j -> i

    搞了两天多终于把这六道题搞完了。。。

    渣代码:

    View Code
      1 #include <iostream>
    2 #include <cstring>
    3 #include <cstdio>
    4 #include <stack>
    5
    6 using namespace std;
    7
    8 const int N = 1024;
    9 const int M = 500000;
    10
    11 struct node {
    12 int to;
    13 int next;
    14 } g[M];
    15
    16 int head[N], scc[N];
    17 int low[N], dfn[N];
    18 int s[N];
    19 bool vis[N];
    20
    21 int hate[2][N], fri[2][N];
    22 int dis1[N], dis2[N];
    23
    24 int t, top, ind, cnt;
    25 int n, a, b, D;
    26
    27 int ABS(int x) {
    28 return x < 0 ? -x : x;
    29 }
    30
    31 void init() {
    32 for(int i = 0; i < N; i++) {
    33 head[i] = dfn[i] = scc[i] = low[i] = vis[i] = 0;
    34 s[i] = 0;
    35 }
    36 t = 1; top = ind = cnt = 0;
    37 }
    38
    39 void add(int u, int v) {
    40 g[t].to = v; g[t].next = head[u]; head[u] = t++;
    41 }
    42
    43 void tarjan(int u) {
    44 int v, i;
    45 dfn[u] = low[u] = ++ind;
    46 s[top++] = u; vis[u] = true;
    47
    48 for(i = head[u]; i; i = g[i].next) {
    49 v = g[i].to;
    50 if(!dfn[v]) {
    51 tarjan(v);
    52 low[u] = min(low[u], low[v]);
    53 } else if(vis[v]) {
    54 low[u] = min(low[u], dfn[v]);
    55 }
    56 }
    57 if(dfn[u] == low[u]) {
    58 cnt++;
    59 do {
    60 v = s[--top];
    61 //printf("**%d %d\n", v, cnt);
    62 scc[v] = cnt;
    63 vis[v] = false;
    64 } while(v != u);
    65 }
    66 }
    67
    68 void rebuild(int lim) {
    69 int i, j, x, y;
    70 for(i = 0; i < a; i++) {
    71 x = hate[0][i]*2; y = hate[1][i]*2;
    72 add(x, y + 1); add(y, x + 1);
    73 add(y + 1, x); add(x + 1, y);
    74 //printf("%d %d\n", x, y);
    75 }
    76 for(i = 0; i < b; i++) {
    77 x = fri[0][i]*2; y = fri[1][i]*2;
    78 add(x, y); add(x + 1, y + 1);
    79 add(y, x); add(y + 1, x + 1);
    80 //printf("%d -> %d\n", x, y);
    81 }
    82 for(i = 0; i < n; i++) {
    83 for(j = i + 1; j < n; j++) {
    84 x = i<<1, y = j << 1;
    85 if(dis1[i] + dis1[j] > lim) {add(x, y + 1); add(y, x + 1);}
    86 if(dis2[i] + dis2[j] > lim) {add(x + 1, y); add(y + 1, x);}
    87 if(dis1[i] + dis2[j] + D > lim) {add(x, y); add(y + 1, x + 1);}
    88 if(dis2[i] + dis1[j] + D > lim) {add(x + 1, y + 1); add(y, x);}
    89 }
    90 }
    91 }
    92
    93 bool solve(int lim) {
    94 init();
    95 rebuild(lim);
    96 for(int i = 0; i < n<<1; i++) {
    97 if(!dfn[i]) tarjan(i);
    98 }
    99 for(int i = 0; i < n; i ++) {
    100 if(scc[i<<1] == scc[i<<1|1]) return false;
    101 }
    102 return true;
    103 }
    104
    105 int main() {
    106 //freopen("data.in", "r", stdin);
    107
    108 int i, m, x, y;
    109 int sx1, sx2, sy1, sy2;
    110 while(~scanf("%d%d%d", &n, &a, &b)) {
    111 scanf("%d%d%d%d", &sx1, &sy1, &sx2, &sy2);
    112 D = ABS(sx1 - sx2) + ABS(sy1 - sy2);
    113 m = -1;
    114 for(i = 0; i < n; i++) {
    115 scanf("%d%d", &x, &y);
    116 dis1[i] = ABS(x - sx1) + ABS(y - sy1);
    117 dis2[i] = ABS(x - sx2) + ABS(y - sy2);
    118 m = max(m, max(dis1[i], dis2[i]));
    119 }
    120 for(i = 0; i < a; i++) {
    121 scanf("%d%d", &hate[0][i], &hate[1][i]);
    122 hate[0][i] --; hate[1][i]--;
    123 }
    124 for(i = 0; i < b; i++) {
    125 scanf("%d%d", &fri[0][i], &fri[1][i]);
    126 fri[0][i]--; fri[1][i]--;
    127 }
    128 int l = 0, r = m*3, mid, ans = -1;
    129 while(l <= r) {
    130 mid = (l + r) >> 1;
    131 if(solve(mid)) {
    132 ans = mid;
    133 r = mid - 1;
    134 }
    135 else l = mid + 1;
    136 //printf("%d %d %d\n", l, r, mid);
    137 }
    138 printf("%d\n", ans);
    139 }
    140 return 0;
    141 }





  • 相关阅读:
    操作系统典型调度算法
    C++ volatile 关键字
    vue class绑定 组件
    yarn 基本用法
    vscode 插件安装以及首选项配置
    git 多人协作
    git Feature分支
    git Bug分支
    git 分支策略
    git 解决冲突
  • 原文地址:https://www.cnblogs.com/vongang/p/2353770.html
Copyright © 2011-2022 走看看