您的位置:首页 > 其它

6.12白书第五章图论总结——司雨寒

2015-06-21 21:02 302 查看
之前我的图论一直都是DFS一下,BFS一下,求个欧拉回路,拓扑排个序这种渣渣水平。

终于鼓起勇气拾起白书第五章的东西。

学(bei)习(song)了一下求双连通分量,二分图的判定,强连通分量,2-SAT。

DFS加上时间戳这个东西,很强大。

最后刷了白书上的例题:

BCC:

LA3523

可以参加会议的是双联通分量上的奇圈

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

const int maxn = 2000 + 10;
int T[maxn][2];

int n;

vector<int> G[maxn * 2];
bool mark[maxn * 2];
int S[maxn * 2], top;

void init()
{
for(int i = 0; i < n * 2; i++) G[i].clear();
memset(mark, false, sizeof(mark));
}

void add_clause(int x, int xvalue, int y, int yvalue)
{
x = x * 2 + xvalue;
y = y * 2 + yvalue;
G[x^1].push_back(y);
G[y^1].push_back(x);
}

bool dfs(int u)
{
if(mark[u^1]) return false;
if(mark[u]) return true;
mark[u] = true;
S[++top] = u;
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i];
if(!dfs(v)) return false;
}
return true;
}

bool solve()
{
for(int i = 0; i < n*2; i += 2)
{
if(!mark[i] && !mark[i+1])
{
top = -1;
if(!dfs(i))
{
while(top >= 0) mark[S[top--]] = false;
if(!dfs(i + 1)) return false;
}
}
}
return true;
}

bool ok(int t)
{
init();
for(int i = 0; i < n; i++) for(int a = 0; a < 2; a++)
for(int j = i + 1; j < n; j++) for(int b = 0; b < 2; b++)
if(abs(T[i][a] - T[j][b]) < t) add_clause(i, a^1, j, b^1);
return solve();
}

int main()
{
//freopen("in.txt", "r", stdin);

while(scanf("%d", &n) == 1)
{
int L = 0, R = 0;
for(int i = 0; i < n; i++)
{
scanf("%d%d", &T[i][0], &T[i][1]);
R = max(R, T[i][0]);
R = max(R, T[i][1]);
}

while(L < R)
{
int mid = (L + R) / 2 + 1;
if(ok(mid)) L = mid;
else R = mid - 1;
}
printf("%d\n", L);
}

return 0;
}


代码君
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: