ACdream-1056 Bad Horse

Bad Horse

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
Problem Description

As the leader of the Evil League of Evil, Bad Horse has a lot of problems to deal with.

Most recently, there have been far too many arguments and far too much backstabbing in the League, so much so that Bad Horse has decided to split the league into two departments in order to separate troublesome members.

Being the Thoroughbred of Sin, Bad Horse isn't about to spend his valuable time figuring out how to split the League members by himself.

That what he's got you -- his loyal henchman -- for.

Input

The first line of the input gives the number of test cases, T (1 ≤ T ≤ 100).

T test cases follow.

Each test case starts with a positive integer M (1 ≤ M ≤ 100) on a line by itself -- the number of troublesome pairs of League members.

The next M lines each contain a pair of names, separated by a single space.

Each member name will consist of only letters and the underscore character "_".

Names are case-sensitive.

No pair will appear more than once in the same test case.

Each pair will contain two distinct League members.

Output

For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1) and y is either "Yes" or "No", depending on whether the League members mentioned in the input can be split into two groups with neither of the groups containing a troublesome pair.

Sample Input
2
1
Dead_Bowie Fake_Thomas_Jefferson
3
Dead_Bowie Fake_Thomas_Jefferson
Fake_Thomas_Jefferson Fury_Leika
Fury_Leika Dead_Bowie

Sample Output
Case #1: Yes
Case #2: No
————————————————————集训9.1的分割线————————————————————

前言:看到这题目,感觉有点熟悉。但是没想起来。事后题目标签变成Bad Horse的时候,我明白了。还记得我刚到实验室的时候,刚认识波哥他们,得知谷歌有办一种Code Jam的比赛,不需要代码,只需要输出文件.out,就去看了它的一个Practice。当然了,那个时候我不知道什么是并查集什么又是Flood_fill。然后就放弃了。看来出来混总是要还的。(链接:https://code.google.com/codejam/contest/dashboard?c=2933486#s=p0)

思路:据说flood_fill可以秒。但是其实这就是一个关系并查集。很裸,关键是要会用STL的map,也要想起来POJ-1182(食物链)才行。两个人有冲突,关系就是1。没有冲突,关系是0。一旦出现既是1又是0,返回False。就秒了。

介绍一下map的使用:

map非常强大。

map <?, ?> MAP:将前者映射到后者

MAP.clear():删除所有元素

MAP.count(?):返回元素出现的次数

示例:(将字符串映射到int)

#include <cstdio>
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
	freopen("test.in", "r", stdin);
	map <string, int> name;
	map <string, int>::iterator iter;
	string str;
	int cnt = 0;
	while(cin >> str) {
		if(name.count(str) == 0)
			name[str] = cnt++;
	}
	for(iter = name.begin(); iter != name.end(); iter++)
		cout << iter->first << " -> " << iter->second << endl;
	return 0;
}
因此,本题的映射可以这样写:

int MAP(string &str)
{
    if(name.count(str) == 0) {
        name[str] = cnt++;
    }
    return name[str];
}
int main() 
{
......
for(int i = 0; i < k; i++) {
            cin >> sa >> sb;
            int a = MAP(sa), b = MAP(sb);
            G[a][b] = G[b][a] = true;
        }
......
}
解决了映射的问题,就剩下裸的并查集。关系的处理,打个2×2的表足矣。

x and y is 1 -> 
[x and fx is 0][y and fy is 0] -> fy and fx is 1
[x and fx is 0][y and fy is 1] -> fy and fx is 0
[x and fx is 1][y and fy is 0] -> fy and fx is 0
[x and fx is 1][y and fy is 1] -> fy and fx is 1
根据x和fx推导x和ffx关系的过程省略。

代码如下:

/*
ID: j.sure.1
PROG:
LANG: C++
*/
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
#define INF 2e9
using namespace std;
/****************************************/
const int N = 500;
const int r_sex[2][2] = {1, 0, 0, 1}, r_gra[2][2] = {0, 1, 1, 0};
map <string, int> name;
string sa, sb;
int fa[N], cnt, rela[N];
bool G[N][N], ok;

int MAP(string &str)
{
    if(name.count(str) == 0) {
        name[str] = cnt++;
    }
    return name[str];
}
 
int Find(int x)
{
    int tmp;
    if(x != fa[x]) {
        tmp = fa[x];
        fa[x] = Find(fa[x]);
        rela[x] = r_gra[rela[x]][rela[tmp]];
    }
    return fa[x];
}
 
void Union(int x, int y)
{
    int fx = Find(x), fy = Find(y);
    if(fx != fy) {
        fa[fy] = fx;
        rela[fy] = r_sex[rela[x]][rela[y]];
        return ;
    }
    if((rela[x] + 1) % 2 != rela[y])
        ok = false;
}
 
int main()
{
#ifdef J_Sure
    freopen("1056.in", "r", stdin);
    freopen("1056.out", "w", stdout);
#endif
    int T, cas = 1;
    scanf("%d", &T);
    while(T--) {
        int k;
        scanf("%d", &k);
        name.clear();
        memset(G, 0, sizeof(G));
        cnt = 0;

        ok = true;
        for(int i = 0; i < k; i++) {
            cin >> sa >> sb;
            int a = MAP(sa), b = MAP(sb);
            G[a][b] = G[b][a] = true;
        }
        for(int i = 0; i < cnt; i++) {
            fa[i] = i;
            rela[i] = 0;
        }
        for(int i = 0; i < cnt; i++) {
            for(int j = i+1; j < cnt; j++) {
                if(G[i][j]) {
                    Union(i, j);
                }
            }
        }
        
        if(!ok)
            printf("Case #%d: No\n", cas++);
        else
            printf("Case #%d: Yes\n", cas++);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值