题目
输入$n$条有向边,确定是否能一笔画,如果能则输出最大的“起点*终点“,否则输出$-1$。
题解
欧拉图模板题。
根据维基百科上的说法,一个连通的有向图有从$u$到$v$欧拉路径的充要条件是$u$的出度比入度多1,$v$的入度比出度多1,其他节点出度等于入度,一个连通的有向图有欧拉回路的充要条件是所有节点的出度等于入度。
所以直接遍历边确定出度和入度就好了。
这题有个坑是给的有向图不一定连通,如果不连通的话当然不会有欧拉路径或欧拉回路。考虑到有向图的单连通+强连通等价于对应无向图的连通,无向图判断连通性的方法有很多,DFS、BFS等等,但是我觉得搜索太麻烦,就用的并查集。
代码
AC代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#include <algorithm> #include <cmath> #include <cstdio> #include <ctime> #include <cstring> #include <iostream> #include <queue> #include <map> #include <set> #include <string> #include <list> #include <forward_list> #include <stack> #include <unordered_set> #include <vector> #include <limits.h>
#define DISPLAY_A 0
using namespace std;
class Edges { public: int u, v, ans;
Edges(int u, int v) : u(u), v(v), ans(u * v) {}
bool operator<(Edges &e) const { return ans < e.ans; } };
int dset[101]; int iSet[101];
int find(int x) { if (dset[x] == x) { return x; } dset[x] = find(dset[x]); return dset[x]; }
int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); int pot[101]; memset(pot, 0, sizeof(int) * 101); int n; cin >> n; int u, v; vector<Edges> ct; for (int i = 0; i < n; i++) { cin >> u >> v; pot[u] -= 1; pot[v] += 1; ct.emplace_back(u, v); if (dset[u]) { if (dset[v]) { if (find(u) != find(v)) { dset[find(v)] = find(u); } } else { dset[v] = find(u); } } else if (dset[v]) { dset[u] = find(v); } else { dset[u] = u; dset[v] = u; } } int numSet = 0; for (int i = 1; i <= 100; i++) { if (!dset[i]) { continue; } int root = find(i); if (!iSet[root]) { iSet[root] = 1; numSet += 1; if (numSet > 1) { cout << -1 << endl; return 0; } } } int start = 0, end = 0; for (int i = 1; i <= 100; i++) { if (pot[i] == 1) { if (!end) { end = i; } else { cout << -1 << endl; return 0; } } else if (pot[i] == -1) { if (!start) { start = i; } else { cout << -1 << endl; return 0; } } else if (pot[i] != 0) { cout << -1 << endl; return 0; } } if (start && end) { cout << start * end << endl; } else if (start == 0 && end == 0) { int maxAns = 0; for (auto &i:ct) { maxAns = max(maxAns, max(i.u, i.v)); } cout << maxAns * maxAns << endl; } else { cout << -1 << endl; } return 0; }
|