二部图判断

这几天没事,就做了Google Code Jam上的3道练习题。

第一题是“Bad Horse”,具体的描述如下:

Problem

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, TT test cases follow. Each test case starts with a positive integer M 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.

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.

Limits

1 ≤ T ≤ 100.
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.

Small dataset

1 ≤ M ≤ 10.

Large dataset

1 ≤ M ≤ 100.

Sample


二部图判断_第1张图片
具体意思是,每一行的两匹马不太合,是不能在呆在一起的,要将他们分开。每个Test Case中的所有马看能不能划分为两组,每组中的马是可以共处的。

这个问题其实就是一个离散数学里二部图问题。解决办法是利用图着色的方法,即利用广度优先搜索(BFS)对图中每个节点用两种颜色进行着色,相邻节点要为不同颜色,如果最后着色成功,则是可以划分为两组的,否则不行。

具体代码如下:
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <string>
#include <map>
#include <queue>

using namespace std;

bool setAdj(map<string, vector<string> > & horse_adj, map<string, int> & horse_color, const string & key)
{
    map<string, int>::iterator itr_horse_color;
    vector<string>::iterator itr_adjs;

    queue<string> bfs_horse;
    queue<int> bfs_color;


    for(itr_adjs = horse_adj[key].begin(); itr_adjs != horse_adj[key].end(); itr_adjs++)
    {
        if(horse_color.find(*itr_adjs) == horse_color.end())
        {
            bfs_horse.push(*itr_adjs);
            bfs_color.push(horse_color[key]);
        }
    }

    int color;
    string horse = "";
    while(!bfs_horse.empty())
    {
        horse = bfs_horse.front();
        bfs_horse.pop();

        color = bfs_color.front();
        bfs_color.pop();

        itr_horse_color = horse_color.find(horse);
        if(itr_horse_color == horse_color.end())
        {
            horse_color.insert(pair<string, int>(horse, -1*color));
        }
        else
        {
            if(horse_color[horse] == color)
            {
                return false;
            }
        }

        for(itr_adjs = horse_adj[horse].begin(); itr_adjs != horse_adj[horse].end(); itr_adjs++)
        {
            if(horse_color.find(*itr_adjs) == horse_color.end())
            {
                bfs_horse.push(*itr_adjs);
                bfs_color.push(horse_color[horse]);
            }
        }
    }
    return true;
}

bool isSplit(map<string, vector<string> > & horse_adj, map<string, int> & horse_color)
{
    map<string, vector<string> >::iterator itr_horse_adj;
    map<string, int>::iterator itr_horse_color;
    vector<string>::iterator itr_adjs;

    vector<string> bfs_horse;
    // cout << horse_adj.size() << endl;
    for(itr_horse_adj = horse_adj.begin(); itr_horse_adj != horse_adj.end(); itr_horse_adj++)
    {
        // cout << itr_horse_adj->first << endl;
        itr_horse_color = horse_color.find(itr_horse_adj->first);
        if(itr_horse_color == horse_color.end())
        {
            // is adj colored?
            bool colored = false;
            for(itr_adjs = (itr_horse_adj->second).begin(); itr_adjs != (itr_horse_adj->second).end(); itr_adjs++)
            {
                itr_horse_color = horse_color.find(*itr_adjs);
                if(itr_horse_color != horse_color.end())
                {
                    horse_color.insert(pair<string, int>(itr_horse_adj->first, -1*(itr_horse_color->second)));
                    // cout << itr_horse_adj->first << ":" << horse_color[itr_horse_adj->first] << endl;
                    colored = true;
                    break;
                }
            }
            if(!colored)
            {
                horse_color.insert(pair<string, int>(itr_horse_adj->first, 1));
                // cout << itr_horse_adj->first << ":" << horse_color[itr_horse_adj->first] << endl;
            }
        }

        if(!setAdj(horse_adj, horse_color, itr_horse_adj->first))
        {
            return false;
        }
    }
    return true;
}


int main(int argc, char* argv[])
{
    int T = 0;
    cin >> T;

    int M = 0;
    map<string, vector<string> > horse_adj;
    map<string, vector<string> >::iterator itr_horse_adj;
    map<string, int> horse_color;

    string line = "";
    string lhorse = "";
    string rhorse = "";

    int pos = -1;
    for(int i = 0; i < T; i++)
    {
        cin >> M;
        for(int j = 0; j < M; j++)
        {
            // getline(cin, line);
            // // cout << line << endl;
            // pos = line.find(" ");
            // lhorse = line.substr(0, pos);
            // rhorse = line.substr(pos + 1);
            cin >> lhorse >> rhorse;
            // cout << lhorse << "\t" << rhorse << endl;
            itr_horse_adj = horse_adj.find(lhorse);
            if(itr_horse_adj == horse_adj.end())
            {
                vector<string> adjs;
                adjs.push_back(rhorse);
                horse_adj.insert(pair<string, vector<string> >(lhorse, adjs));
                adjs.clear();
            }
            else
            {
                (itr_horse_adj->second).push_back(rhorse);
            }

            itr_horse_adj = horse_adj.find(rhorse);
            if(itr_horse_adj == horse_adj.end())
            {
                vector<string> adjs;
                adjs.push_back(lhorse);
                horse_adj.insert(pair<string, vector<string> >(rhorse, adjs));
                adjs.clear();
            }
            else
            {
                (itr_horse_adj->second).push_back(lhorse);
            }
        }
        // cout << horse_adj.size() << endl;
        if(isSplit(horse_adj, horse_color))
        {
            cout << "Case #" << i + 1 << ": Yes" << endl;
        }
        else
        {
            cout << "Case #" << i + 1 << ": No" << endl;
        }

        horse_adj.clear();
        horse_color.clear();
    }
}

其中,图是利用邻接表来表示的,bool setAdj()是利用BFS的方法将图中的节点进行着色,所以需要使用一个queue。

要注意的是,如果图是连通图,只要bool setAdj()就可以将所有点着色了,但是如果图是非连通图,就必须扫描节点了,看所有节点是否都已着色,所以bool isSplit()需要一个循环来扫描所有节点(可能可以优化)。

你可能感兴趣的:(C++,二部图)