标签:efi com ace mes 数据 amp $2 tin stdin
题目链接:http://codeforces.com/contest/788/problem/B
数据范围:略。
题解:
我们发现就是要求,把每条无向边拆成两条无向边,其中有两条拆成一条,问这个图有没有欧拉回路。
无向图欧拉回路的充要条件是度数为奇数的点数等于$0$或者$2$。
那么我们的删边方式就分成了三种:
第一种,删任意两个自环。
第二种,删一个自环和任意一条边。
第三种,删两条有公共端点的边,
随便枚举一下就行。
代码:
#include <bits/stdc++.h> #define N 1000010 using namespace std; typedef long long ll; char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ ) int rd() { int x = 0, f = 1; char c = nc(); while (c < 48) { if (c == ‘-‘) f = -1; c = nc(); } while (c > 47) { x = (((x << 2) + x) << 1) + (c ^ 48), c = nc(); } return x * f; } int n, m, t; ll d[N]; int zh[N]; bool vis[N]; int tot, head[N], nxt[N << 1], to[N << 1]; inline void add(int x, int y) { to[ ++ tot] = y; nxt[tot] = head[x]; head[x] = tot; } void dfs(int p) { vis[p] = true; for (int i = head[p]; i; i = nxt[i]) { if (!vis[to[i]]) { dfs(to[i]); } } } int main() { n = rd(), m = rd(); for (int i = 1; i <= m; i ++ ) { int x = rd(), y = rd(); add(x, y), add(y, x); if (x == y) { t ++ , zh[x] ++ ; continue; } d[x] ++ , d[y] ++ ; } for (int i = 1; i <= n; i ++ ) { if (d[i]) { dfs(i); break; } } for (int i = 1; i <= n; i ++ ) { if (!vis[i]) { if (d[i] || zh[i]) { puts("0"); return 0; } } } ll ans = 0; ans += (ll)t * (t - 1) / 2; ans += (ll)t * (m - t); for (int i = 1; i <= n; i ++ ) { if (d[i] >= 2) { ans += (ll)d[i] * (d[i] - 1) / 2; } } cout << ans << endl ; return 0; }
标签:efi com ace mes 数据 amp $2 tin stdin
原文地址:https://www.cnblogs.com/ShuraK/p/11761402.html