我正在使用邻接列表表示对无向图进行二分测试。用户输入节点及其连接的内容,每行是一对。例如:
0 1
2 3
1 2
0 3
表示0连接到1和3,2连接到1和3等。算法执行BFS,着色节点,并查看它是否可以是二分。除了查看图表是否为二分图之外,它还按排序顺序存储和输出哪些节点属于哪个组。按照前面的例子,1和3将在A组中,2和0将是B组。样本输出将是:
Group A:
0
2
Group B:
1
3
我可以说,目前的算法工作正常,几乎没有问题,节省了一些"凌乱"代码位在这里和那里可以清理。这是整个计划:
#include <iostream>
#include<vector>
#include<queue>
#include<map>
#include<list>
#include<algorithm>
#include<set>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
vector<int>vec[50];
map<int,int>color;
queue<int>q;
vector<int> B;
vector<int> H;
bool check(int n, int src){
q.push(src);
int i;
color[src]=1;
while(!q.empty()){
src = q.front();
q.pop();
for(i=0;i<vec[src].size();i++){
if(color[vec[src][i]]==-1){ //vec[src][i] = data; color[src] = color;
color[vec[src][i]]= 1 - color[src];
q.push(vec[src][i]);
if (color[src] == 0
and find(B.begin(), B.end(), vec[src][i]) == B.end()
and find(H.begin(), H.end(), vec[src][i]) == H.end()){
B.push_back(vec[src][i]); }
else if (color[src] == 1
and find(B.begin(), B.end(), vec[src][i]) == B.end()
and find(H.begin(), H.end(), vec[src][i]) == H.end()){
H.push_back(vec[src][i]); }
}
else if(color[vec[src][i]]== color[src]){
return 0; }
else{
if(find(B.begin(), B.end(), vec[src][i]) != B.end()){
break; }
else if(find(H.begin(), H.end(), vec[src][i]) != H.end()){
break; }
else{ B.push_back(vec[src][i]); }
}
}
}
return 1;
}
int distinct(const vector<int>& v){
set<int> distinct_container;
for(auto curr_int = v.begin(), end = v.end(); curr_int != end; ++curr_int){
distinct_container.insert(*curr_int); }
return distinct_container.size();
}
int main() {
int inp; int index = 0; vector<int> Input;
while (cin >> inp){
Input.push_back(inp); }
int points = distinct(Input);
while(index < points){
color[index]= - 1; index++; }
index = 0;
while(index < Input.size()){
vec[Input[index]].push_back(Input[index + 1]);
vec[Input[index + 1]].push_back(Input[index]);
index += 2;
}
bool res = 1; index = 0;
for(int i = 0; i < points; i++){
if(color[i]==-1){
res = res && check(points, i); }
}
if(res){
sort(B.begin(), B.end());
sort(H.begin(), H.end());
cout << "Group A:\n"; int x = 0;
while (x < B.size()){
cout << B[x] << "\n"; x++; }
cout << "Group B:\n"; int y = 0;
while (y < H.size()){
cout << H[y] << "\n"; y++; }
}
else{
cout << "IMPOSSIBLE"; }
return 0;
}
现在,我遇到的问题是我必须将节点转换为字符串作为数据,而不是整数。我没有像1和2那样配对数字,而是按照与前一个示例相同的输入语法配对像Jane和Frank这样的名称:它们之间的单个空格表示配对。仍在测试节点,如果他们是两党,在搜索中将它们着色,将它们添加到矢量中,以便稍后在各自的组中输出。所有改变的都是输入的数据类型。而且我的尝试没有取得任何进展。
非常感谢任何帮助。我主要是在寻找数据类型的解决方案,但我会对其中的任何一个采取批评和建议。请给我一些更多的工作。提前谢谢。
编辑:按照kraskevich给我的想法,我想我有点想法。但是我遇到了两个新问题:在最后将地图重新组合在一起输出名称,而当前算法(无论输入如何)都返回IMPOSSIBLE。
新代码:只有主要更改,以及更多向量的额外全局声明。
map<string, int> toNum;
vector<string> numToString;
vector<int> BN;
vector<int> HN;
vector<string> BS;
vector<string> HS;
................
int main(){
string s; vector<int> Input; int edges = 0;
while (cin >> s){
edges++; }
int id; int index = 0; int points = 0;
if (toNum.find(s) != toNum.end()){
id = toNum[s]; }
else{
numToString.push_back(s);
toNum.insert( pair<int, string>(numToString.size() - 1, s));
id = numToString.size() - 1; ++points;
Input.push_back(id); }
while(index < points){
color[index]= - 1; index++; }
index = 0;
while(index < numToString.size()){
vec[Input[index]].push_back(Input[index + 1]);
vec[Input[index + 1]].push_back(Input[index]);
index += 2;
}
bool res = 1; index = 0;
for(int i = 0; i < points; i++){
if(color[i]==-1){
res = res && check(points, i); }
}
if(res){
index = 0; int key = 0; string name;
while (index < BN.size()){
name = toNum[BN[index]];
BS.push_back(name);
index++; }
index = 0;
while (index < HN.size()){
name = toNum[BN[index]];
HS.push_back(name);
index++; }
sort(BS.begin(), BS.end());
sort(HS.begin(), HS.end());
cout << "GROUP A\n"; int x = 0;
while (x < BS.size()){
cout << BS[x] << "\n"; x++; }
cout << "GROUP B\n"; int y = 0;
while (y < HS.size()){
cout << HS[y] << "\n"; y++; }
}
else{
cout << "IMPOSSIBLE"; }
return 0;
}
答案 0 :(得分:1)
我不会改变广度优先搜索的实现。相反,您可以简单地将所有字符串映射到数字,运行现有实现,然后将数字映射回字符串。
如何预先形成映射?这样的事情:
// A mapping from strings to their ids.
std::map<std::string, int> toNum;
// A mapping from ids to strings.
std::vector<std::string> numToString;
...
std::string s;
std::cin >> s;
int id;
if (toNum.find(s) != toNum.end()) {
id = toNum[s];
} else {
numToString.push_back(s);
id = numToString.size() - 1;
toNum[s] = id;
}