A-Z Graph

\(A-Z Graph\)(啊这图)

又是一个毒瘤构造题

给定有向图有n个点,每条边上有个字符,支持三种操作,加一条边,删去一条边,查询是否存在包含k个点的路径满足经过的边形成的字符串和反向经过这些点形成的字符串相同,可以访问同一个点任意次。

考虑特殊情况的构造,首先必须要有连接两个点不同方向的边,对于两个点之间连接的边,如果正向和反向相同,那么对于任意长度存在,如果不同则对于偶数个点的情况存在解,否则无解。

可以发现这个构造是充分的,因为对于偶数个点存在解的情况,中间经过的那条边必然正向等于反向。

#include<bits/stdc++.h>

using namespace std;

#define fore(i, l, r) for(int i = int(l); i < int(r); i++)
#define sz(a) int((a).size())

#define x first
#define y second

typedef pair<int, int> pt;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    int n, m;
    cin >> n >> m;
    
    map<pt, int> allEdges;
    set<pt> difPairs, eqPairs;
    
    fore (q, 0, m) {
        char tp; cin >> tp;
        if (tp == '+') {
            int u, v;
            char c;
            cin >> u >> v >> c;
            
            if (allEdges.count({v, u})) {
                if (allEdges[{v, u}] == c)
                    eqPairs.emplace(min(u, v), max(u, v));
                else
                    difPairs.emplace(min(u, v), max(u, v));
            }
            allEdges[{u, v}] = c;
            
        } else if (tp == '-') {
            int u, v;
            cin >> u >> v;
            if (eqPairs.count({min(u, v), max(u, v)}))
                eqPairs.erase({min(u, v), max(u, v)});
            if (difPairs.count({min(u, v), max(u, v)}))
                difPairs.erase({min(u, v), max(u, v)});
            
            allEdges.erase({u, v});
        } else {
            int k;
            cin >> k;
            
            bool hasAns = !eqPairs.empty();
            if (k & 1)
                hasAns |= !difPairs.empty();
            cout << (hasAns ? "YES" : "NO") << '\n';
        }
    }
    
    return 0;
}
posted @ 2021-03-09 22:22  dinlon  阅读(70)  评论(0)    收藏  举报