您的位置:首页 > 其它

二分图判定+点染色/并查集 BestCoder Round #48 ($) 1002 wyh2000 and pupil

2015-07-19 13:27 381 查看
题目传送门

 /*
二分图判定+点染色:因为有很多联通块,要对所有点二分图匹配,若不能,存在点是无法分配的,no
每一次二分图匹配时,将点多的集合加大最后第一个集合去
注意:n <= 1,no,两个集合都至少有一人;ans == n,扔一个给另一个集合
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <map>
using namespace std;

const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
vector<int> G[MAXN];
int col[MAXN];
int cnt[3];
int n, m;

bool DFS(int u)
{
for (int i=0; i<G[u].size (); ++i)
{
int v = G[u][i];
if (col[v] == -1) {
col[v] = 3 - col[u];    cnt[col[v]]++;
if (!DFS (v))   return false;
}
else if (col[v] == col[u])  return false;
}

return true;
}

void work(void)
{
memset (col, -1, sizeof (col));
int ans = 0;
for (int i=1; i<=n; ++i)
{
if (col[i] == -1)
{
col[i] = 1; cnt[1] = 1; cnt[2] = 0;
if (!DFS (i)) {
puts ("Poor wyh");  return ;
}
ans += max (cnt[1], cnt[2]);
}
}
if (ans == n)   ans--;
printf ("%d %d\n", ans, n - ans);
}

int main(void)      //BestCoder Round #48 ($) 1002    wyh2000 and pupil
{
int t;   scanf ("%d", &t);
while (t--)
{
scanf ("%d%d", &n, &m);
if (n <= 1) {
puts ("Poor wyh");  continue;
}
for (int i=1; i<=n; ++i)    G[i].clear ();
for (int i=1; i<=m; ++i)
{
int u, v;   scanf ("%d%d", &u, &v);
G[u].push_back (v); G[v].push_back (u);
}
work ();
}

return 0;
}


 /*
并查集:有点像POJ食物链的做法, 分为(1, n)和(n+1, 2*n)两个集合,两种情况都试一下。
rt[i] == -1表示是该集合的根,用sz数组记录集合的大小
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <map>
using namespace std;

const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int n, m;
struct UF   {
int rt[MAXN*2], sz[MAXN*2], sz2[MAXN*2];
void init(void) {
memset (rt, -1, sizeof (rt));
for (int i=1; i<=2*n; ++i)  sz[i] = (i <= n), sz2[i] = (i > n);
}
int Find(int x) {
return rt[x] == -1 ? x : rt[x] = Find (rt[x]);
}
void Union(int x, int y)    {
x = Find (x);   y = Find (y);
if (x == y) return ;
rt[x] = y;
sz[y] += sz[x]; sz2[y] += sz2[x];
}
bool same(int x, int y) {
return Find (x) == Find (y);
}
}uf;

int main(void)      //BestCoder Round #48 ($) 1002    wyh2000 and pupil
{
int t;   scanf ("%d", &t);
while (t--)
{
scanf ("%d%d", &n, &m);
bool ok = true; uf.init ();
for (int i=1; i<=m; ++i)
{
int u, v;   scanf ("%d%d", &u, &v);
if (!ok)   continue;
if (uf.same (u, v) || uf.same (u+n, v+n))   ok = false;
else    uf.Union (u, v+n), uf.Union (u+n, v);
}

if (!ok || n <= 1)    puts ("Poor wyh");
else if (m == 0)    printf ("%d 1\n", n - 1);
else    {
int ans = 0;
for (int i=1; i<=n; ++i)    {
if (uf.rt[i] == -1) {
ans += min (uf.sz[i], uf.sz2[i]);
}
}
printf ("%d %d\n", n - ans, ans);
}
}

return 0;
}


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