您的位置:首页 > 其它

poj 1703 poj 2492 并查集 桥梁判AB组

2015-07-20 10:22 387 查看
poj 1703:

题意:

有N名来自两个帮派的小弟,已知一些小弟不属于同一帮派。

判断给定两个小弟是否属于同一帮派。

解析:

并查集。

A表示小弟在帮派A,B表示小弟在帮派B。

将所有点拆成两组,当做桥梁。

样例:

5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4

如下图所示:

1. A 1 2

初始访问,肯定是不确定的。

2.D 1 2

得知两者不在一个帮派,所以将 1 和 2 + n = 7 并入并查集,这样7就当做了一条桥梁,如果还有与2这个点不同帮派的,就直接将其归入了1门下。

同理,将 2 和 1 + n = 6 并入并查集。



3.A 1 2

此时,1 和 2 + n = 7 属于同一连通块,所以他们不在同一帮派。

4.D 2 4

这一步是理解桥梁作用的重点。

得知,2 与 4 不再同一个帮派,所以 2 与 4 + n = 9 合并,4 与 2 + n = 7 合并。

此时 7 便作为了逻辑上的桥梁,将 1 与 4 同一帮派的连在了一起。



5.A 1 4

因而,这俩货在同一个帮派。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

int fa[maxn << 1];
int height[maxn << 1];

void Init(int n)
{
for (int i = 1; i <= n; i++)
{
fa[i] = i;
height[i] = 0;
}
}

int Find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = Find(fa[x]);
}

void Union(int u, int v)
{
int fau = Find(u);
int fav = Find(v);
if (fau == fav)
return;
if (height[fau] < height[fav])
{
fa[fau] = fav;
}
else
{
fa[fav] = fau;
if (height[fau] == height[fav])
{
height[fau]++;
}
}
}

bool Same(int u, int v)
{
return Find(u) == Find(v);
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ncase;
scanf("%d", &ncase);
while (ncase--)
{
int n, m;
scanf("%d%d", &n, &m);
Init(n << 1);
while (m--)
{
char op[5];
int fr, to;
scanf("%s", op);
scanf("%d%d", &fr, &to);
if (op[0] == 'A')
{
if (Same(fr, to))
{
printf("In the same gang.\n");
}
else if (Same(fr, to + n))
{
printf("In different gangs.\n");
}
else
{
printf("Not sure yet.\n");
}
}
else
{
Union(fr, to + n);
Union(fr + n, to);
}
}
}
return 0;
}


poj 2492:

题意:

有一种昆虫n只,他们的标号1-n,现在做了交配试验(雾),来判断他们是否有同性恋存在。

每次给出两只昆虫的标号,代表他们在交配(大雾)。

解析:

同上题,帮派变成了性别。

每次给出的两只昆虫应该是不同性别的,因此加入并查集。

若属同一性别,则试验失败。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 2000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

int fa[maxn << 1];
int height[maxn << 1];

void Init(int n)
{
for (int i = 1; i <= n; i++)
{
fa[i] = i;
height[i] = 0;
}
}

int Find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = Find(fa[x]);
}

void Union(int u, int v)
{
int fau = Find(u);
int fav = Find(v);
if (fau == fav)
return;
if (height[fau] < height[fav])
{
fa[fau] = fav;
}
else
{
fa[fav] = fau;
if (height[fau] == height[fav])
{
height[fau]++;
}
}
}

bool Same(int u, int v)
{
return Find(u) == Find(v);
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ncase;
scanf("%d", &ncase);
int ca = 1;
while (ncase--)
{
int n, m;
scanf("%d%d", &n, &m);
Init(n << 1);
bool flag = true;
while (m--)
{
int fr, to;
scanf("%d%d", &fr, &to);
if (Same(fr, to))
{
flag = false;
}
Union(fr, to + n);
Union(fr + n, to);
}
printf("Scenario #%d:\n", ca++);
if (!flag)
printf("Suspicious bugs found!\n\n");
else
printf("No suspicious bugs found!\n\n");
}
return 0;
}


提高:

食物链:

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