为什么我会为UVa 10511的这个解决方案获得WA

时间:2015-01-03 23:49:42

标签: algorithm

我正在努力解决这个问题,我想我已经得到了正确答案,但我仍然得到法官的WA(错误回答)回复。

http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1452

提出的问题是,在党和人之间建立1 - *关系,1 - *人和俱乐部之间的关系。找到人与俱乐部之间的1 - 1关系,这样对于与俱乐部相关的所有人,属于任何一方的人数不到俱乐部数量的一半。

例如,假设我们有

Person1属于Party1和Club1,Club2

Person2属于Party2和Club2,Club3

Person3属于Party3和Club3,Club1

可能有两项任务。

Person1 Club1

Person2 Club2

Person3 Club3

Person1 Club2

Person2 Club3

Person3 Club1

我的想法是将此问题建模为最大流量问题,如下所示:

为简单起见,假设有两个派对,四个人和三个俱乐部。

0是主要来源

1,2是代表双方的节点

3,4,5,6是代表四个人的节点

7,8,9是代表三个俱乐部的节点。

10是主汇

主要来源连接到容量=(3 + 1)/ 2 - 1 = 1的每一方。这表示理事会中代表的一方最多只能有1人(否则2将等于或超过一半)

对于每个派对人员,都有一个容量为1的链接。这表示每个人只有一方,并在先前分配的号码中使用了一个席位。

对于每个人俱乐部对,都有一个容量为1的链接。这表示每个人只能代表一个俱乐部。

最后但并非最不重要的是,所有俱乐部都会以容量1进入下沉。

如果上图中最大流量等于俱乐部数量 - 则存在分配。

我可以证明设计是正确的如下:

=>

如果存在大小的最大流量,则每个球杆节点必须发送值为1的流量,暗示每个球杆节点恰好有一个人代表它。该表示尊重党参与的约束,因为它最多由党节点代表的一方中的许多人流动。

&LT =

如果有表示,则按上述方式构造流程,以便存在流程。流量是最大的,因为最大可能的流量受到连接到水槽的边缘的限制。

因此,无论是上述参数还是实施,都必定是错误的。

不用多说,这是我的源代码:

#include "stdafx.h"

// http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1452

// #define LOG

#include "UVa10511.h"

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <queue>

using namespace std;

int UVa10511_assign_person_number(map<string, int>& person_numbers, map<int, string>& person_namings, string person_name);
int UVa10511_assign_party_number(map<string, int>& party_numbers, map<int, string>& party_namings, string party_name);
int UVa10511_assign_club_number(map<string, int>& club_numbers, map<int, string>& club_namings, string club_name);
int UVa10511_Edmonds_Karps(vector<vector<int>>& capacities, vector<vector<int>>& adjacency_list, int src, int dst);

int UVa10511()
{
    string line;
    int number_of_test_cases;
    cin >> number_of_test_cases;
    getline(cin, line); // consume the blank link after the number of test cases    
    getline(cin, line); // consume the blank link before the first test case
    for (int test_case = 0; test_case < number_of_test_cases; test_case++)
    {
        map<string, int> person_numbers;
        map<int, string> person_namings;
        map<string, int> party_numbers;
        map<int, string> party_namings;
        map<string, int> club_numbers;
        map<int, string> club_namings;

        vector<pair<int, int>> party_members;
        vector<pair<int, int>> person_clubs;

        while(getline(cin, line) && line != "" && line != " ")
        {
            string person_name;
            string party_name;
            string club_name;
            stringstream sin(line);
            sin >> person_name >> party_name;

            int person_id = UVa10511_assign_person_number(person_numbers, person_namings, person_name);
            int party_id = UVa10511_assign_party_number(party_numbers, party_namings, party_name);
            party_members.push_back(pair<int, int>(party_id, person_id));
            while(sin >> club_name)
            {
                int club_id = UVa10511_assign_club_number(club_numbers, club_namings, club_name);
                person_clubs.push_back(pair<int, int>(person_id, club_id));
            }   
        }

        int number_of_parties = party_numbers.size();
        int number_of_persons = person_numbers.size();
        int number_of_clubs = club_numbers.size();

        int number_of_nodes =
            /* master source */ 1 +
            /* parties       */ number_of_parties +
            /* person        */ number_of_persons +
            /* clubs         */ number_of_clubs +
            /* master sink   */ 1;

        vector<vector<int>> capacities;
        vector<vector<int>> adjacency_list;

        capacities.resize(number_of_nodes);
        adjacency_list.resize(number_of_nodes);

        for (int src = 0; src < number_of_nodes; src++)
        {
            capacities[src].resize(number_of_nodes);
            for (int dst = 0; dst < number_of_nodes; dst++)
            {
                capacities[src][dst] = 0;
            }
        }

        int max_party_participants = (number_of_clubs - 1) / 2; // Floor intended, not equal or more than half

        for (int p = 0; p < number_of_parties; p++)
        {
            int party_node = p + 1;
            capacities[0][party_node] = max_party_participants;
            adjacency_list[0].push_back(party_node);
            adjacency_list[party_node].push_back(0);
        }

        int person_node_start = 1 + number_of_parties;

        for (vector<pair<int, int>>::iterator pmi = party_members.begin(); pmi != party_members.end(); pmi++)
        {
            int party_id = pmi->first;
            int person_id = pmi->second;

            int party_node = party_id + 1;
            int person_node = person_node_start + person_id;

            capacities[party_node][person_node] = 1;
            adjacency_list[party_node].push_back(person_node);
            adjacency_list[person_node].push_back(party_node);
        }

        int club_node_start = 1 + number_of_parties + number_of_persons;
        for (vector<pair<int, int>>::iterator pci = person_clubs.begin(); pci != person_clubs.end(); pci++)
        {
            int person_id = pci->first;
            int club_id = pci->second;

            int person_node = person_node_start + person_id;
            int club_node = club_node_start + club_id;

            capacities[person_node][club_node] = 1;
            adjacency_list[person_node].push_back(club_node);
            adjacency_list[club_node].push_back(person_node);
        }

        for (int c = 0; c < number_of_clubs; c++)
        {
            int club_node = club_node_start + c;
            capacities[club_node][number_of_nodes - 1] = 1;
            adjacency_list[club_node].push_back(number_of_nodes - 1);
            adjacency_list[number_of_nodes - 1].push_back(club_node);
        }

#ifdef LOG
        cout << "digraph {" << endl;
        for (int src = 0; src < number_of_nodes; src++)
        {
            for (vector<int>::iterator di = adjacency_list[src].begin(); di != adjacency_list[src].end(); di++)
            {
                int dst = *di;
                cout << src << "->" << dst << " [label=\"" << capacities[src][dst] << "\"];" << endl;
            }
        }
        cout << "}" << endl;
#endif

        int total_flow = UVa10511_Edmonds_Karps(capacities, adjacency_list, 0, number_of_nodes - 1);

        if (test_case > 0)
        {
            cout << endl;
        }

        if (total_flow == number_of_clubs)
        {

            for (vector<pair<int, int>>::iterator pci = person_clubs.begin(); pci != person_clubs.end(); pci++)
            {
                int person_id = pci->first;
                int club_id = pci->second;

                int person_node = person_node_start + person_id;
                int club_node = club_node_start + club_id;

                if (capacities[person_node][club_node] == 0)
                {
                    cout << person_namings[person_id] << " " << club_namings[club_id] << endl;
                }
            }
        }
        else
        {
            cout << "Impossible." << endl;
        }
    }

    return 0;
}

int UVa10511_assign_party_number(map<string, int>& party_numbers, map<int, string>& party_namings, string party_name)
{
    int party_number;
    map<string, int>::iterator probe = party_numbers.find(party_name);
    if (probe == party_numbers.end())
    {
        party_number = party_numbers.size();
        party_numbers.insert(pair<string, int>(party_name, party_number));
        party_namings.insert(pair<int, string>(party_number, party_name));
    }
    else
    {
        party_number = probe->second;
    }

    return party_number;
}

int UVa10511_assign_person_number(map<string, int>& person_numbers, map<int, string>& person_namings, string person_name)
{
    int person_number;
    map<string, int>::iterator probe = person_numbers.find(person_name);
    if (probe == person_numbers.end())
    {
        person_number = person_numbers.size();
        person_numbers.insert(pair<string, int>(person_name, person_number));
        person_namings.insert(pair<int, string>(person_number, person_name));
    }
    else
    {
        person_number = probe->second;
    }

    return person_number;
}

int UVa10511_assign_club_number(map<string, int>& club_numbers, map<int, string>& club_namings, string club_name)
{
    int club_number;
    map<string, int>::iterator probe = club_numbers.find(club_name);
    if (probe == club_numbers.end())
    {
        club_number = club_numbers.size();
        club_numbers.insert(pair<string, int>(club_name, club_number));
        club_namings.insert(pair<int, string>(club_number, club_name));
    }
    else
    {
        club_number = probe->second;
    }

    return club_number;
}

int UVa10511_Edmonds_Karps(vector<vector<int>>& capacities, vector<vector<int>>& adjacency_list, int src, int dst)
{
    int total_flow = 0;
    // Step 2: Edmonds Karp's
    vector<int> parents; // Allow back-tracking the path found from bfs
    int number_of_nodes = capacities.size();
    parents.resize(number_of_nodes); // avoid reallocation
    while (true)
    {
        // Step 2.1: Use BFS to find an augmenting flow
        queue<int> bfs_queue;
        for (int n = 0; n < number_of_nodes; n++)
        {
            parents[n] = -1; // indicating the node is not enqueued
        }

        parents[src] = -2; // indicating the node is enqueued but no actual parent because this is the root
        bfs_queue.push(src);
        while (bfs_queue.size() > 0)
        {
            int current = bfs_queue.front();
            bfs_queue.pop();
            for (vector<int>::iterator ni = adjacency_list[current].begin(); ni != adjacency_list[current].end(); ni++)
            {
                int neighbor = *ni;
                if (parents[neighbor] == -1 && capacities[current][neighbor] > 0)
                {
                    parents[neighbor] = current;
                    bfs_queue.push(neighbor);

                    if (neighbor == dst)
                    {
                        break;
                    }
                }
            }
            if (parents[dst] != -1)
            {
                break;
            }
        }

        if (parents[dst] == -1)
        {
            break;
        }
        else
        {
            // We have found an augmenting path, go through the path and find the max flow through this path
            int cur = dst;
            bool first = true;
            int max_flow_through_path = 0;
            while (true)
            {
                int src = parents[cur];
                if (src != -2)
                {
                    int dst = cur;
                    int available = capacities[src][dst];
#ifdef LOG
                    cout << src << "--" << available << "->" << dst << endl;
#endif
                    cur = parents[cur];
                    if (first)
                    {
                        max_flow_through_path = available;
                        first = false;
                    }
                    else
                    {
                        max_flow_through_path = min(max_flow_through_path, available);
                    }
                }
                else
                {
                    break;
                }
            }
#ifdef LOG
            cout << "flowing " << max_flow_through_path << endl << endl;
#endif
            total_flow += max_flow_through_path;
            // Flow the max flow through the augmenting path
            cur = dst;
            while (true)
            {
                int src = parents[cur];
                if (src != -2)
                {
                    capacities[src][cur] -= max_flow_through_path;
                    capacities[cur][src] += max_flow_through_path;
                    cur = parents[cur];
                }
                else
                {
                    break;
                }
            }
        }
    }

    return total_flow;
}

源代码也发布在 https://github.com/cshung/Competition/blob/master/Competition/UVa10511.cpp

相同的Edmonds Karps程序用于传递其他一些UVa问题,所以我认为应该没问题。

这种Edmonds Karp手术均可接受UVa820,UVa10480,UVa10779,UVa11506,UVa563 (这些代码也可以在Git存储库中找到)

我甚至调试了Edmond Karps做出错误选择的情况,并修复了这个测试用例的扩充路径

1

Person1 Party1 Club1 Club2

Person2 Party2 Club3

Person3 Party3 Club1

由于我的Edmond Karps在邻接列表顺序中使用了BFS,所选路径为

主要来源 - &gt; Party1 - &gt; Person1 - &gt; Club1 - &gt; Master Sink

主要来源 - &gt; Party2 - &gt; Person2 - &gt; Club3 - &gt; Master Sink

主要来源 - &gt; Party3 - &gt; Person3 - &gt; Club1 - &gt; Person1 - &gt; Club2 - &gt;主接收器[这使用反向边缘并证明通过反向边缘工作]

现在我真的被卡住了,真的不知道什么是错的,感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您对此问题的思考是正确的,这是使用最大流量算法的典型问题。

我一遍又一遍地阅读你的代码,我找不到任何错误。然后我改变你处理输入的方式,然后我接受了UVA。

只需更改代码

即可
// you code 
cin >> number_of_test_cases;
getline(cin, line); // consume the blank link before the first test case
getline(cin, line); // consume the blank link before the first test case

//line 43
while(getline(cin, line) && line != "" && line != " ")

// change to
scanf("%d\n", &number_of_test_cases);

//line 43
// while(getline(cin, line) && line.length() > 0)

更改代码后,我接受了uva的接受。

希望得到你的回应。