POJ 2296与POJ 3678建图有一个地方要注意,即类似 a && b == 1,则a和b都必须为1,那么需要添加两条边~a->a,~b->b。
POJ 2296有一种情况是必须加边的,即:两个矩形的坐标差不超过边长时,只可能一种情况,就是一个在上,一个在下,那么就需用到上述的加边。
POJ 2296:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <map> using namespace std; const int maxn = 210; const int maxm = 210*210*5; const int INF = 0x3f3f3f3f; struct Edge { int v, w; int next; }edge[maxm]; int first[maxn], stack[maxn], ins[maxn], dfn[maxn], low[maxn]; int belong[maxn]; int n, m; int cnt; int scnt, top, tot; void init() { cnt = 0; scnt = top = tot = 0; memset(first, -1, sizeof(first)); memset(dfn, 0, sizeof(dfn)); memset(ins, 0, sizeof(ins)); memset(low, 0, sizeof(low)); } void read_graph(int u, int v) { edge[cnt].v = v; edge[cnt].next = first[u], first[u] = cnt++; } void dfs(int u) { int v; low[u] = dfn[u] = ++tot; stack[top++] = u; ins[u] = 1; for(int e = first[u]; e != -1; e = edge[e].next) { v = edge[e].v; if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(ins[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { scnt++; do { v = stack[--top]; belong[v] = scnt; ins[v] = 0; } while(u != v); } } void Tarjan() { for(int v = 0; v < 2*n; v++) if(!dfn[v]) dfs(v); } void readint(int &x) { char c; while(!isdigit(c)) c = getchar(); x = 0; while(isdigit(c)) { x = x*10 + c-'0'; c = getchar(); } } void writeint(int x) { if(x > 9) writeint(x/10); putchar(x%10+'0'); } struct Point { int x, y; Point() {} Point(int x, int y): x(x), y(y) {} }P[maxn]; void read_case() { init(); readint(n); for(int i = 0; i < n; i++) { int x, y; scanf("%d%d", &x, &y); P[i] = Point(x, y); } } void build(int mid) { init(); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(i != j) { if(abs(P[i].x-P[j].x) < mid) { int dif = P[i].y - P[j].y; if(dif < 2*mid && dif >= mid) { read_graph(i+n, j+n); } else if(dif > 0 && dif < mid) //i为必选,那么连一条边~i->i { read_graph(i+n, i); } else if(dif == 0) { read_graph(i, j+n); read_graph(i+n, j); } else if(dif < 0 && dif > -mid) { read_graph(i, i+n); } else if(dif <= -mid && dif > -2*mid) { read_graph(i, j); } } } Tarjan(); } int ok() { for(int i = 0; i < n; i++) if(belong[i] == belong[i+n]) return 0; return 1; } int BSearch(int x, int y) { int ans = -1; while(x <= y) { int mid = x+(y-x)/2; build(mid); if(ok()) { ans = mid; x = mid+1; } else y = mid-1; } return ans; } void solve() { read_case(); int ans = BSearch(0, 20010); writeint(ans), puts(""); } int main() { int T; for(readint(T); T--; ) solve(); return 0; }
POJ 3678 :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <map> using namespace std; const int maxn = 2010; const int maxm = 1010*1010*5; const int INF = 0x3f3f3f3f; struct Edge { int v, w; int next; int id; }edge[maxm]; int first[maxn], stack[maxn], ins[maxn], dfn[maxn], low[maxn]; int belong[maxn]; int n, m; int cnt; int scnt, top, tot; void init() { cnt = 0; scnt = top = tot = 0; memset(first, -1, sizeof(first)); memset(dfn, 0, sizeof(dfn)); memset(ins, 0, sizeof(ins)); memset(low, 0, sizeof(low)); } void read_graph(int u, int v) { edge[cnt].v = v; edge[cnt].next = first[u], first[u] = cnt++; } void dfs(int u) { int v; low[u] = dfn[u] = ++tot; stack[top++] = u; ins[u] = 1; for(int e = first[u]; e != -1; e = edge[e].next) { v = edge[e].v; if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(ins[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { scnt++; do { v = stack[--top]; belong[v] = scnt; ins[v] = 0; } while(u != v); } } void Tarjan() { for(int v = 0; v < 2*n; v++) if(!dfn[v]) dfs(v); } void readint(int &x) { char c; while(!isdigit(c)) c = getchar(); x = 0; while(isdigit(c)) { x = x*10 + c-'0'; c = getchar(); } } void writeint(int x) { if(x > 9) writeint(x/10); putchar(x%10+'0'); } void read_case() { init(); char op[10]; while(m--) { int x, y, z; scanf("%d%d%d%s", &x, &y, &z, &op); if(op[0] == 'A') { if(z) { read_graph(x, x+n); read_graph(y, y+n); } else { read_graph(x+n, y); read_graph(y+n, x); } } else if(op[0] == 'O') { if(z) { read_graph(x, y+n); read_graph(y, x+n); } else { read_graph(x+n, x); read_graph(y+n, y); } } else if(op[0] == 'X') { if(z) { read_graph(x, y+n), read_graph(x+n, y); read_graph(y, x+n), read_graph(y+n, x); } else { read_graph(x, y), read_graph(y, x); read_graph(x+n, y+n), read_graph(y+n, x+n); } } } } int ok() { for(int i = 0; i < n; i++) if(belong[i] == belong[i+n]) return 0; return 1; } void solve() { read_case(); Tarjan(); if(ok()) printf("YES "); else printf("NO "); } int main() { while(~scanf("%d%d", &n, &m)) { solve(); } return 0; }
特殊的连边方式: http://blog.sina.com.cn/s/blog_68629c7701010gf1.html