#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <map>
using namespace std;
struct POINTS
{
float xStart;
float yStart;
float zStart;
float xEnd;
float yEnd;
float zEnd;
};
vector<POINTS> generate_lines(int n)
{
vector<POINTS> lines;
for (int i = 0; i < n; i++)
{
POINTS p;
p.xStart = i ? lines.rbegin()->xEnd : rand()/static_cast<float>(RAND_MAX);
p.yStart = i ? lines.rbegin()->yEnd : rand()/static_cast<float>(RAND_MAX);
p.zStart = i ? lines.rbegin()->zEnd : rand()/static_cast<float>(RAND_MAX);
p.xEnd = i == n-1 ? lines.begin()->xStart : rand()/static_cast<float>(RAND_MAX);
p.yEnd = i == n-1 ? lines.begin()->yStart : rand()/static_cast<float>(RAND_MAX);
p.zEnd = i == n-1 ? lines.begin()->zStart : rand()/static_cast<float>(RAND_MAX);
lines.push_back(p);
}
random_shuffle(lines.begin(), lines.end());
for (auto &p : lines)
if (rand()%2)
{
swap(p.xStart, p.xEnd);
swap(p.yStart, p.yEnd);
swap(p.zStart, p.zEnd);
}
return lines;
}
int main()
{
vector<POINTS> lines = generate_lines(10);
multimap<tuple<double, double, double>, pair<double, double> > M;
for (int i = 0; i < lines.size(); i++)
{
// add start point
M.insert(make_pair(make_tuple(lines[i].xStart, lines[i].yStart, lines[i].zStart),
make_pair(i, 0) ) );
M.insert(make_pair(make_tuple(lines[i].xEnd, lines[i].yEnd, lines[i].zEnd),
make_pair(i, 1) ) );
}
auto coords1 = M.begin()->first;
auto pos1 = M.begin()->second;
vector<bool> used(lines.size(), false);
for (int i = 0; i < lines.size(); i++)
{
std::tuple<double, double, double> coords2 = pos1.second ? make_tuple(lines[pos1.first].xStart, lines[pos1.first].yStart, lines[pos1.first].zStart) :
make_tuple(lines[pos1.first].xEnd, lines[pos1.first].yEnd, lines[pos1.first].zEnd);
cout << pos1.first << ": " << get<0>(coords1) << " " << get<1>(coords1) << " " << get<2>(coords1) << " - "
<< get<0>(coords2) << " " << get<1>(coords2) << " " << get<2>(coords2) << endl;
used[pos1.first] = true;
pair<int, int> nextPos(-1, -1);
auto r = M.equal_range(coords2);
for (auto it = r.first; it != r.second; it++)
if (!used[it->second.first])
{
nextPos = it->second;
break;
}
if (nextPos.first == -1 && i != lines.size()-1)
{
cout << "something bad happens\n";
return 1;
}
pos1 = nextPos;
coords1 = coords2;
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPG1hcD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgpzdHJ1Y3QgUE9JTlRTCnsKICAgZmxvYXQgeFN0YXJ0OwogICBmbG9hdCB5U3RhcnQ7CiAgIGZsb2F0IHpTdGFydDsKCiAgIGZsb2F0IHhFbmQ7CiAgIGZsb2F0IHlFbmQ7CiAgIGZsb2F0IHpFbmQ7Cn07Cgp2ZWN0b3I8UE9JTlRTPiBnZW5lcmF0ZV9saW5lcyhpbnQgbikKewogICAgdmVjdG9yPFBPSU5UUz4gbGluZXM7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICB7CiAgICAgICAgUE9JTlRTIHA7CgogICAgICAgIHAueFN0YXJ0ID0gaSA/IGxpbmVzLnJiZWdpbigpLT54RW5kIDogcmFuZCgpL3N0YXRpY19jYXN0PGZsb2F0PihSQU5EX01BWCk7CiAgICAgICAgcC55U3RhcnQgPSBpID8gbGluZXMucmJlZ2luKCktPnlFbmQgOiByYW5kKCkvc3RhdGljX2Nhc3Q8ZmxvYXQ+KFJBTkRfTUFYKTsKICAgICAgICBwLnpTdGFydCA9IGkgPyBsaW5lcy5yYmVnaW4oKS0+ekVuZCA6IHJhbmQoKS9zdGF0aWNfY2FzdDxmbG9hdD4oUkFORF9NQVgpOwoKICAgICAgICBwLnhFbmQgPSBpID09IG4tMSA/IGxpbmVzLmJlZ2luKCktPnhTdGFydCA6IHJhbmQoKS9zdGF0aWNfY2FzdDxmbG9hdD4oUkFORF9NQVgpOwogICAgICAgIHAueUVuZCA9IGkgPT0gbi0xID8gbGluZXMuYmVnaW4oKS0+eVN0YXJ0IDogcmFuZCgpL3N0YXRpY19jYXN0PGZsb2F0PihSQU5EX01BWCk7CiAgICAgICAgcC56RW5kID0gaSA9PSBuLTEgPyBsaW5lcy5iZWdpbigpLT56U3RhcnQgOiByYW5kKCkvc3RhdGljX2Nhc3Q8ZmxvYXQ+KFJBTkRfTUFYKTsKCiAgICAgICAgbGluZXMucHVzaF9iYWNrKHApOwogICAgfQoKICAgIHJhbmRvbV9zaHVmZmxlKGxpbmVzLmJlZ2luKCksIGxpbmVzLmVuZCgpKTsKCiAgICBmb3IgKGF1dG8gJnAgOiBsaW5lcykKICAgICAgICBpZiAocmFuZCgpJTIpCiAgICAgICAgewogICAgICAgICAgICBzd2FwKHAueFN0YXJ0LCBwLnhFbmQpOwogICAgICAgICAgICBzd2FwKHAueVN0YXJ0LCBwLnlFbmQpOwogICAgICAgICAgICBzd2FwKHAuelN0YXJ0LCBwLnpFbmQpOwogICAgICAgIH0KCiAgICByZXR1cm4gbGluZXM7Cn0KCmludCBtYWluKCkKewogICAgdmVjdG9yPFBPSU5UUz4gbGluZXMgPSBnZW5lcmF0ZV9saW5lcygxMCk7CiAgICBtdWx0aW1hcDx0dXBsZTxkb3VibGUsIGRvdWJsZSwgZG91YmxlPiwgcGFpcjxkb3VibGUsIGRvdWJsZT4gPiBNOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbGluZXMuc2l6ZSgpOyBpKyspCiAgICB7CiAgICAgICAgLy8gYWRkIHN0YXJ0IHBvaW50CiAgICAgICAgTS5pbnNlcnQobWFrZV9wYWlyKG1ha2VfdHVwbGUobGluZXNbaV0ueFN0YXJ0LCBsaW5lc1tpXS55U3RhcnQsIGxpbmVzW2ldLnpTdGFydCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ha2VfcGFpcihpLCAwKSApICk7CgogICAgICAgIE0uaW5zZXJ0KG1ha2VfcGFpcihtYWtlX3R1cGxlKGxpbmVzW2ldLnhFbmQsIGxpbmVzW2ldLnlFbmQsIGxpbmVzW2ldLnpFbmQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBtYWtlX3BhaXIoaSwgMSkgKSApOwogICAgfQoKICAgIGF1dG8gY29vcmRzMSA9IE0uYmVnaW4oKS0+Zmlyc3Q7CiAgICBhdXRvIHBvczEgPSBNLmJlZ2luKCktPnNlY29uZDsKCiAgICB2ZWN0b3I8Ym9vbD4gdXNlZChsaW5lcy5zaXplKCksIGZhbHNlKTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IGxpbmVzLnNpemUoKTsgaSsrKQogICAgewogICAgICAgIHN0ZDo6dHVwbGU8ZG91YmxlLCBkb3VibGUsIGRvdWJsZT4gY29vcmRzMiA9IHBvczEuc2Vjb25kID8gbWFrZV90dXBsZShsaW5lc1twb3MxLmZpcnN0XS54U3RhcnQsIGxpbmVzW3BvczEuZmlyc3RdLnlTdGFydCwgbGluZXNbcG9zMS5maXJzdF0uelN0YXJ0KSA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWtlX3R1cGxlKGxpbmVzW3BvczEuZmlyc3RdLnhFbmQsIGxpbmVzW3BvczEuZmlyc3RdLnlFbmQsIGxpbmVzW3BvczEuZmlyc3RdLnpFbmQpOwoKICAgICAgICBjb3V0IDw8IHBvczEuZmlyc3QgPDwgIjogIiA8PCBnZXQ8MD4oY29vcmRzMSkgPDwgIiAiIDw8IGdldDwxPihjb29yZHMxKSA8PCAiICIgPDwgZ2V0PDI+KGNvb3JkczEpIDw8ICIgLSAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPDwgZ2V0PDA+KGNvb3JkczIpIDw8ICIgIiA8PCBnZXQ8MT4oY29vcmRzMikgPDwgIiAiIDw8IGdldDwyPihjb29yZHMyKSA8PCBlbmRsOwoKICAgICAgICB1c2VkW3BvczEuZmlyc3RdID0gdHJ1ZTsKCiAgICAgICAgcGFpcjxpbnQsIGludD4gbmV4dFBvcygtMSwgLTEpOwoKICAgICAgICBhdXRvIHIgPSBNLmVxdWFsX3JhbmdlKGNvb3JkczIpOwogICAgICAgIGZvciAoYXV0byBpdCA9IHIuZmlyc3Q7IGl0ICE9IHIuc2Vjb25kOyBpdCsrKQogICAgICAgICAgICBpZiAoIXVzZWRbaXQtPnNlY29uZC5maXJzdF0pCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIG5leHRQb3MgPSBpdC0+c2Vjb25kOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KCiAgICAgICAgaWYgKG5leHRQb3MuZmlyc3QgPT0gLTEgJiYgaSAhPSBsaW5lcy5zaXplKCktMSkKICAgICAgICB7CiAgICAgICAgICAgIGNvdXQgPDwgInNvbWV0aGluZyBiYWQgaGFwcGVuc1xuIjsKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQoKICAgICAgICBwb3MxID0gbmV4dFBvczsKICAgICAgICBjb29yZHMxID0gY29vcmRzMjsKICAgIH0KCiAgICByZXR1cm4gMDsKfQo=