图论——2SAT

SRM464 DIV1 500pt:

比较裸滴,二分+2SAT判定。由于数据量很小,floyd足矣~

View Code
#include <iostream>
#include
<cstdio>
#include
<cstring>
#include
<vector>
usingnamespace std;

class ColorfulDecoration
{
public:
conststaticint inf =1000000000;
bool map[105][105];

int abs(int x)
{
if(x <0) x =-x;
return x;
}

int getMaximum(vector <int> xa, vector <int> ya, vector <int> xb, vector <int> yb)
{
int i, j, k, l, r, mid, x1, y1, x2, y2, n = xa.size();
int ans;
l
=0, r = inf;
while(l <= r)
{
mid
= (l+r) >>1;
memset(map,
false, sizeof(map));
for(i =0; i < n+n; i++)
for(j = i+1; j< n+n; j++)
if(i%n != j%n)
{
x1
= (i < n) ? xa[i] : xb[i-n];
y1
= (i < n) ? ya[i] : yb[i-n];
x2
= (j < n) ? xa[j] : xb[j-n];
y2
= (j < n) ? ya[j] : yb[j-n];
if(abs(x1-x2)<mid && abs(y1-y2)<mid)
{
map[i][(j
<n)? j+n:j-n] =true;
map[j][(i
<n)? i+n:i-n] =true;
}
}
for(k =0; k < n+n; k++)
for(i =0; i < n+n; i++)
{
if(i == k) continue;
for(j =0; j < n+n; j++)
if(j != k)
map[i][j]
= map[i][j] || (map[i][k] && map[k][j]);
}
for(i =0; i < n; i++)
if(map[i][i+n] && map[i+n][i])
break;
if(i == n)
{
ans
= mid;
l
= mid +1;
}
else r = mid-1;
}
return ans;
}
};

 

pku2749:

部分限定关系已经给出来了,只是距离那个地方不是很好办。

首先二分距离limit,然后把事先给定的约束关系建好,如果a,b不能共存则a->b+n , b->a+n, a+n->b, b+n->a;如果a,b必须共存,则a->b, b->a, a+n->b+n, b+n->a+n。

然后距离约束方面分4中情况:

if(dis1[i]+dis1[j] > limit)  map[i][j+n] = map[j][i+n] =true;
if(dis2[i]+dis2[j] > limit) map[i+n][j] = map[j+n][i] =true;
if(dis1[i]+dd+dis2[j] > limit) map[i][j] = map[j+n][i+n] =true;
if(dis2[i]+dd+dis1[j] > limit) map[i+n][j+n] = map[j][i] =true;
View Code
#include <iostream>
#include
<cstdio>
#include
<cstring>
usingnamespace std;

constint N =1010;
constint inf =10000000;

struct node
{
int x, y;
}a[N], b[N];

int n, dd, A, B, sx1, sy1, sx2, sy2, dis1[N<<1], dis2[N<<1];
bool map[N][N];

int ct, top, depth, index[N], stack[N], d[N], low[N];
bool instack[N];

int Abs(int x)
{
if(x <0) x =-x;
return x;
}

void dfs(int u)
{
int i, x;
instack[u]
=true;
stack[
++top] = u;
d[u]
= low[u] = depth++;
for(i =1; i <= n+n; i++)
if(map[u][i])
{
if(d[i] ==-1)
{
dfs(i);
low[u]
= min(low[u], low[i]);
}
else
{
if(instack[i]) low[u] = min(low[u], d[i]);
}
}
if(d[u] == low[u])
{
ct
++;
while(top)
{
x
= stack[top--];
index[x]
= ct;
instack[x]
=false;
if(x == u) break;
}
}
}

bool check(int limit)
{
int i, j, x, y;
memset(map,
false, sizeof(map));
for(i =1; i <= n; i++)
for(j =1; j <= n; j++)
if(i != j)
{
if(dis1[i]+dis1[j] > limit) map[i][j+n] = map[j][i+n] =true;
if(dis2[i]+dis2[j] > limit) map[i+n][j] = map[j+n][i] =true;
if(dis1[i]+dd+dis2[j] > limit) map[i][j] = map[j+n][i+n] =true;
if(dis2[i]+dd+dis1[j] > limit) map[i+n][j+n] = map[j][i] =true;
}
for(i =1; i <= A; i++)
{
x
= a[i].x, y = a[i].y;
map[x][y
+n] =true;
map[y][x
+n] =true;
map[x
+n][y] =true;
map[y
+n][x] =true;
}
for(i =1; i <= B; i++)
{
x
= b[i].x, y = b[i].y;
map[x][y]
= map[y][x] =true;
map[x
+n][y+n] = map[y+n][x+n] =true;
}
depth
= ct = top =0;
memset(d,
-1, sizeof(d));
memset(instack,
false, sizeof(instack));
for(i =1; i <= n+n; i++)
if(d[i] ==-1)
dfs(i);
for(i =1; i <= n; i++)
if(index[i] == index[i+n])
returnfalse;
returntrue;
}

int main()
{
int i, x, y, l, r, mid, ans;
scanf(
"%d%d%d", &n, &A, &B);
scanf(
"%d%d%d%d", &sx1, &sy1, &sx2, &sy2);
dd
= Abs(sx1-sx2)+Abs(sy1-sy2);
for(i =1; i <= n; i++)
{
scanf(
"%d%d", &x, &y);
dis1[i]
= Abs(x-sx1)+Abs(y-sy1);
dis2[i]
= Abs(x-sx2)+Abs(y-sy2);
}
for(i =1; i <= A; i++)
{
scanf(
"%d%d", &x, &y);
a[i].x
= x, a[i].y = y;
map[x][y
+n] =true;
map[y][x
+n] =true;
map[x
+n][y] =true;
map[y
+n][x] =true;
}
for(i =1; i <= B; i++)
{
scanf(
"%d%d", &x, &y);
b[i].x
= x, b[i].y = y;
map[x][y]
= map[y][x] =true;
map[x
+n][y+n] = map[y+n][x+n] =true;
}
l
=0, r = inf;
if(!check(inf)) ans =-1;
else
{
while(l <= r)
{
mid
= (l+r) >>1;
if(check(mid))
{
ans
= mid;
r
= mid-1;
}
else l = mid+1;
}
}
printf(
"%d\n", ans);
return0;
}

  

pku2723:

这个题。。。还是相对来说比较裸一点的2-SAT吧~首先,最多可以打开几道门可以二分答案。然后怎样判定能不能打开limit扇门呢?假设对于给定的钥匙对有某一对是(a, b),如果后面门上有一对锁是(b, c),假设选了key a,就由a向c连一条边,意思是如果选了key a,那么必定要选key c,因为b在选完a后会消失,如此建图直接2-SAT就可以了。

View Code
#include <iostream>
#include
<cstdio>
#include
<cstring>
usingnamespace std;

constint N =1050;

struct node
{
int x, y;
}key[N],
lock[N<<1];

int n, m;
bool map[N<<1][N<<1];

int ct, top, depth, d[N<<1], low[N<<1], index[N<<1], stack[N<<1];
bool instack[N<<1];

void dfs(int u)
{
int i, x;
instack[u]
=true;
stack[
++top] = u;
d[u]
= low[u] = depth++;
for(i =0; i < n+n; i++)
if(map[u][i])
{
if(d[i] ==-1)
{
dfs(i);
low[u]
= min(low[u], low[i]);
}
else
{
if(instack[i])
low[u]
= min(low[u], d[i]);
}
}
if(low[u] == d[u])
{
ct
++;
while(top)
{
x
= stack[top--];
instack[x]
=false;
index[x]
= ct;
if(x == u) break;
}
}
}

bool check(int limit)
{
int i, j;
memset(map,
false, sizeof(map));
for(i =0; i < n; i++)
{
for(j =0; j <= limit; j++)
{
if(lock[j].x == key[i].y) map[key[i].x][lock[j].y] =true;
if(lock[j].y == key[i].y) map[key[i].x][lock[j].x] =true;
}
for(j =0; j <= limit; j++)
{
if(lock[j].x == key[i].x) map[key[i].y][lock[j].y] =true;
if(lock[j].y == key[i].x) map[key[i].y][lock[j].x] =true;
}
}
ct
= top= depth =0;
memset(d,
-1, sizeof(d));
memset(instack,
false, sizeof(instack));
for(i =0; i < n+n; i++)
if(d[i] ==-1)
dfs(i);
for(i =0; i < n; i++)
if(index[key[i].x] == index[key[i].y])
returnfalse;
returntrue;
}

int main()
{
int i, l, r, mid, ans;
while(scanf("%d%d", &n, &m) != EOF)
{
if(n==0&& m==0) break;
for(i =0; i < n; i++) scanf("%d%d", &key[i].x, &key[i].y);
for(i =0; i < m; i++) scanf("%d%d", &lock[i].x, &lock[i].y);
l
=0, r = m-1;
ans
=-1;
while(l <= r)
{
mid
= (l+r) >>1;
if(check(mid))
{
ans
= mid;
l
= mid+1;
}
else r = mid-1;
}
printf(
"%d\n", ans+1);
}
return0;
}

  

pku3683:

这个,建图比较好建,不过输出的过程用的代码可能有点多。。。注意输出时婚礼的顺序要跟输入一样,偶这个白痴竟然给他排序了,刚开始还找不出原因。。。。。

View Code
#include <iostream>
#include
<cstdio>
#include
<cstring>
#include
<vector>
#include
<algorithm>
usingnamespace std;

constint N =1010;

struct node
{
int s, t, d;
}p[N];

int n;

int ct, depth, top, index[N<<1], d[N<<1], low[N<<1], stack[N<<1];
bool instack[N<<1], map[N<<1][N<<1], g[N<<1][N<<1];

int tot, et[N<<1], color[N<<1], op[N<<1];
bool visit[N<<1];

vector
<int> ans;

void initData()
{
int i, j, x, y, l1, r1, l2, r2;
scanf(
"%d", &n);
for(i =0; i < n; i++)
{
scanf(
"%d:%d", &x, &y);
p[i].s
= x*60+y;
scanf(
"%d:%d", &x, &y);
p[i].t
= x*60+y;
scanf(
"%d", &p[i].d);
}
memset(map,
false, sizeof(map));
for(i =0; i < n; i++)
for(j =0; j < n; j++)
{
if(i == j) continue;

l1
= p[i].s, r1 = p[i].s+p[i].d, l2 = p[j].s, r2 = p[j].s+p[j].d;
if(l1==l2 && r1==r2) map[i][j+n] =true;
if((l1>l2 && l1<r2) || (r1>l2 && r1<r2)) map[i][j+n] =true;
if((l2>l1 && l2<r1) || (r2>l1 && r2<r1)) map[i][j+n] =true;

l1
= p[i].s, r1 = p[i].s+p[i].d, l2 = p[j].t-p[j].d, r2 = p[j].t;
if(l1==l2 && r1==r2) map[i][j] =true;
if((l1>l2 && l1<r2) || (r1>l2 && r1<r2)) map[i][j] =true;
if((l2>l1 && l2<r1) || (r2>l1 && r2<r1)) map[i][j] =true;

l1
= p[i].t-p[i].d, r1 = p[i].t, l2 = p[j].s, r2 = p[j].s+p[j].d;
if(l1==l2 && r1==r2) map[i+n][j+n] =true;
if((l1>l2 && l1<r2) || (r1>l2 && r1<r2)) map[i+n][j+n] =true;
if((l2>l1 && l2<r1) || (r2>l1 && r2<r1)) map[i+n][j+n] =true;

l1
= p[i].t-p[i].d, r1 = p[i].t, l2 = p[j].t-p[j].d, r2 = p[j].t;
if(l1==l2 && r1==r2) map[i+n][j] =true;
if((l1>l2 && l1<r2) || (r1>l2 && r1<r2)) map[i+n][j] =true;
if((l2>l1 && l2<r1) || (r2>l1 && r2<r1)) map[i+n][j] =true;
}
}

void dfs(int u)
{
int i, x;
d[u]
= low[u] = depth++;
stack[
++top] = u;
instack[u]
=true;
for(i =0; i < n+n; i++)
if(map[u][i])
{
if(d[i] ==-1)
{
dfs(i);
low[u]
= min(low[u], low[i]);
}
else
{
if(instack[i])
low[u]
= min(low[u], d[i]);
}
}
if(low[u] == d[u])
{
ct
++;
while(top)
{
x
= stack[top--];
instack[x]
=false;
index[x]
= ct;
if(x == u) break;
}
}
}

void buildNewGraph()
{
int i, j;
memset(g,
false, sizeof(g));
for(i =0; i < n+n; i++)
for(j =0; j < n+n; j++)
if(map[i][j])
g[index[i]][index[j]]
=true;
for(i =1; i <= ct; i++)
for(j = i+1; j <= ct; j++)
swap(g[i][j], g[j][i]);
for(i =0; i < n; i++)
{
op[index[i]]
= index[i+n];
op[index[i
+n]] = index[i];
}
}

void transDfs(int u)
{
int i;
visit[u]
=true;
for(i =1; i <= ct; i++)
if(!visit[i] && g[u][i])
transDfs(i);
et[
++tot] = u;
}

void colorDfs(int u)
{
int i;
color[u]
=0;
for(i =1; i <= ct; i++)
if(color[i]==-1&& g[u][i])
colorDfs(i);
}

void generateAns()
{
int i;
memset(visit,
false, sizeof(visit));
tot
=0;
for(i =1; i <= ct; i++)
if(!visit[i])
transDfs(i);
memset(color,
-1, sizeof(color));
for(i = ct; i >0; i--)
if(color[et[i]] ==-1)
{
color[et[i]]
=1;
colorDfs(op[et[i]]);
}
}

void printAns()
{
int i, pos, x1, y1, x2, y2, len = ans.size();
for(i =0; i < len; i++)
{
pos
= ans[i];
if(pos < n)
{
x1
= p[pos].s/60, y1 = p[pos].s %60;
x2
= (p[pos].s+p[pos].d)/60, y2 = (p[pos].s+p[pos].d)%60;
}
else
{
pos
-= n;
x1
= (p[pos].t-p[pos].d)/60, y1 = (p[pos].t-p[pos].d)%60;
x2
= p[pos].t/60, y2 = p[pos].t%60;
}
printf(
"%d%d:%d%d %d%d:%d%d\n", x1/10, x1%10, y1/10, y1%10, x2/10, x2%10, y2/10, y2%10);
}
}

void solve()
{
int i;
depth
= top = ct =0;
memset(d,
-1, sizeof(d));
memset(instack,
false, sizeof(instack));
for(i =0; i < n+n; i++)
if(d[i] ==-1)
dfs(i);
for(i =0; i < n; i++)
if(index[i] == index[i+n])
break;
if(i < n) printf("NO\n");
else
{
printf(
"YES\n");
buildNewGraph();
generateAns();
ans.clear();
for(i =0; i < n; i++)
if(color[index[i]] ==1)
ans.push_back(i);
else ans.push_back(i+n);
//sort(ans.begin(), ans.end());
printAns();
}
}

int main()
{
initData();
solve();
return0;
}

  

 

 

 

posted on 2011-08-12 09:44  Moon_1st  阅读(2025)  评论(0编辑  收藏  举报

导航