Codeforces Gym 101174 K. Balls and Needles (DFS)

来源:互联网 发布:关于程序员的小说 编辑:程序博客网 时间:2024/06/05 10:37

Problem

给定 K 组三维线段 x1 y1 z1 x2 y2 z2 ,判断是否存在 3 条边构成环。同时将三维线段投射到二维平面上,构成若干二维线段 x1 y1 x2 y2 (可能有重合),判断是否存在 3 条二维线段构成环。

限制条件

1 ≤ K ≤ 50000

1xi, yi, zi1000

解题思路

通过离散化将三维点和二维点作为点编号,记录二维线段和三维线段(通过两端点的编号形式保存)。DFS 深搜,标记遍历到的点的深度,若存在已记录深度的点的深度较之再次遍历到该点的深度差 2 。则存在对应维度的环。

代码

#include<bits/stdc++.h>using namespace std;struct Node {    int x, y, z;} p, q;bool operator<(Node a, Node b) {    if(a.x == b.x) {        if(a.y == b.y)  return a.z < b.z;        return a.y < b.y;    }    return a.x < b.x;}map<Node, int> d2, d3;int K, d2idx, d3idx, vis[2][100010];vector<int> g[2][100010];bool isLink[2];void dfs(int lv, int rt, int dep){    if(isLink[lv])  return;    vis[lv][rt] = dep;    for(int i=0;i<g[lv][rt].size();i++)    {        if(vis[lv][ g[lv][rt][i] ]) {            if(dep - vis[lv][g[lv][rt][i]] >= 2) {  isLink[lv] = true;  return; }            continue;        }        dfs(lv, g[lv][rt][i], dep+1);    }}int main(){    scanf("%d", &K);    for(int i=1;i<=K;i++)    {        scanf("%d %d %d %d %d %d", &p.x, &p.y, &p.z, &q.x, &q.y, &q.z);        if(d3.find(p) == d3.end())  d3[p] = ++d3idx;        if(d3.find(q) == d3.end())  d3[q] = ++d3idx;        g[1][ d3[p] ].push_back(d3[q]);        g[1][ d3[q] ].push_back(d3[p]);        p.z = q.z = 0;        if(d2.find(p) == d2.end())  d2[p] = ++d2idx;        if(d2.find(q) == d2.end())  d2[q] = ++d2idx;        g[0][ d2[p] ].push_back(d2[q]);        g[0][ d2[q] ].push_back(d2[p]);    }    for(int i=1;i<=d3idx;i++)    {        if(vis[1][i])   continue;        dfs(1, i, 1);    }    for(int i=1;i<=d2idx;i++)    {        if(vis[0][i])   continue;        dfs(0, i, 1);    }    printf("%s\n%s\n", isLink[1]?"True closed chains":"No true closed chains",            isLink[0]?"Floor closed chains":"No floor closed chains");}