欧拉路径 hdu 3018 Ant Trip
2014-03-18 16:03
417 查看
给定一个无向图,每条边只走一次,可以有多个出发点,最多要多少个出发点?(不考虑孤立点)
即找至少需要多少个欧拉路径
首先判断联通分量。再在每个连通分量中,奇数度点个数为0,需要出发点1个(欧拉回路);奇数度点位非0个(记为cnt),需要出发点cnt / 2个
一个连通图(无向图)中,奇数度点的个数为偶数个。
证明:
简单说,所有点的度数之和等于边的个数的2倍,为偶数,所以奇数度点的个数为偶数个
图中点的个数记为n,边的个数记为m,则所有点度的和为2m(偶数),偶数度点的度之和为sum_even(显然为偶数),则2m - sum_even(也为偶数)表示奇数度点的度之和。
每个奇数度点可以表示为2a(i)+1;设奇数度点个数为num_old,则有num_old+ 2(a(1)...+...a(num_old))= 2m - sum_even(偶数),则num_old为偶数,因此得证。
一连通图(无向图)中,奇数度点有cnt个(非0),则需要出发点个数为cnt/2;
cnt/2的解一定是可以构造出来的。
但是为什么能保证是最少的呢????下面是自己的理解:
走一个环时,只能最多减少0个奇数度的点。走一个非环的路径时,只能最多减少2个奇数度的点。(正确性???)
则一条路径,一条路径的走。每走完一条路径之后图中减少2个奇数度的点。最后减少到只有2个奇数度个点,则此时一个欧拉路径走完。所以共有至少cnt/2个;
并查集解法:
即找至少需要多少个欧拉路径
首先判断联通分量。再在每个连通分量中,奇数度点个数为0,需要出发点1个(欧拉回路);奇数度点位非0个(记为cnt),需要出发点cnt / 2个
一个连通图(无向图)中,奇数度点的个数为偶数个。
证明:
简单说,所有点的度数之和等于边的个数的2倍,为偶数,所以奇数度点的个数为偶数个
图中点的个数记为n,边的个数记为m,则所有点度的和为2m(偶数),偶数度点的度之和为sum_even(显然为偶数),则2m - sum_even(也为偶数)表示奇数度点的度之和。
每个奇数度点可以表示为2a(i)+1;设奇数度点个数为num_old,则有num_old+ 2(a(1)...+...a(num_old))= 2m - sum_even(偶数),则num_old为偶数,因此得证。
一连通图(无向图)中,奇数度点有cnt个(非0),则需要出发点个数为cnt/2;
cnt/2的解一定是可以构造出来的。
但是为什么能保证是最少的呢????下面是自己的理解:
走一个环时,只能最多减少0个奇数度的点。走一个非环的路径时,只能最多减少2个奇数度的点。(正确性???)
则一条路径,一条路径的走。每走完一条路径之后图中减少2个奇数度的点。最后减少到只有2个奇数度个点,则此时一个欧拉路径走完。所以共有至少cnt/2个;
并查集解法:
//#pragma warning (disable: 4786) //#pragma comment (linker, "/STACK:16777216") //HEAD #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <vector> #include <iostream> #include <algorithm> using namespace std; //LOOP #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FD(i, b, a) for(int i = (b); i>= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(A,value) memset(A,value,sizeof(A)) #define CPY(a, b) memcpy(a, b, sizeof(a)) #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++) //INPUT #define RI(n) scanf("%d", &n) #define RII(n, m) scanf("%d%d", &n, &m) #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k) #define RS(s) scanf("%s", s) typedef long long LL; const int INF = 1000000007; const double eps = 1e-10; const int maxn = 200010; int n, m; int fa[maxn]; int num[maxn];///记录连通分量中点的个数 int sum_old[maxn];///记录连通分量中奇数度点的个数 int X[maxn], Y[maxn]; void init(int n) { for (int i = 0; i <= n; i++) { fa[i] = i; num[i] = 1; sum_old[i] = 0; } } int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } int main () { int x, y; while (cin >> n >> m) { init(n); for (int i = 0; i < m; i++) { RII(x, y); sum_old[x] ^= 1; sum_old[y] ^= 1; X[i] = x; Y[i] = y; } for (int i = 0; i < m; i++) { int fax = find(X[i]); int fay = find(Y[i]); if (fax != fay) { fa[fax] = fay; num[fay] += num[fax]; sum_old[fay] += sum_old[fax]; } } int ans = 0; for (int i = 1; i <= n; i++) { if (find(i) == i && num[i] != 1) { if (sum_old[i] == 0) ans++; else ans += sum_old[i] / 2; } } cout << ans << endl; } return 0; }
相关文章推荐
- hdu-3018 Ant Trip(欧拉路径)
- HDU 3018 Ant Trip (欧拉路径)
- HDU 3018 Ant Trip(欧拉路径 + 并查集 + 连通性判断)
- HDU 3018 Ant Trip
- HDU 1116(并查集,欧拉路径)
- hdu 3018 Ant Trip
- HDU 3472 HS BDC (混合图的欧拉路径判断)
- HDU 1116 && UVA 10129 && POJ 1386 ------ Play on Words(欧拉路径 + 并查集)
- hdu 3472 混合图的欧拉路径
- [欧拉回路] hdu 3018 Ant Trip
- hdu acm 3018 Ant Trip
- hdu 3018 Ant Trip
- HDU 3018-Ant Trip(并查集&&欧拉)
- HDU 3472 HS BDC 混合图的欧拉路径
- hdu 3018 Ant Trip
- [欧拉回路] hdu 3018 Ant Trip
- hdu 4850 Wow! Such String! 构造 或 欧拉路径并改写成非递归版本
- hdu 3018 Ant Trip
- HDU 3018 Ant Trip
- HDU 5883 The Best Path(欧拉路径\回路)