Codeforces 91C Ski Base 加边求欧拉回路数量

题目链接:点击打开链接

题意:

给出n个点m条无向边的图

开始图里没有边,每次加一条边,然后输出图里欧拉回路的条数。

思路:

We will count the number of ski bases including the base consisted of empty subset of edges (before printing just subtract one). In the beginning the number of bases is equal to 1.
If we connect vertexes in the same connected components then the result should be multiplied by 2 else do nothing. You should use DJS data structure to know information
about connected components where vertexes are and to unite them.

Why is it correct?

To prove it we will use the matrix of incidence I, rows in it will be edges and columns will be vertexes. Let‘s define xor of
two rows. Xor of two rows a и b will
be row c such that ci?=?ai xor bi.
Notice if  xor of some subset of rows is equal to a zero row then this subset form the ski base. It‘s correct because, the degree of contiguity of every
vertex is even, so we can form an Euler cycle in every connected component. The answer is  2(m?-?rank(I)).

Why it is correct? Let‘s write the number of edge from the right of each row which suit this row. While finding the matrix rank using gauss method with xor operation,
we will xor the subsets from the right of the strings. In the end the subsets of edges written from the right of the zero rows will form the basis of the
linear space. Thats why we can take any subset of vectors from basis and make up a new ski base. The number of these subsets is equal to 2k = 2(m?-?rank(I)),
where k is the number of zero rows.

The last thing we should notice that the adding row is liner depended if and only if there is exist a way between the vertexes a and b (aand b are
the ends of the adding edge).

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
const int N = 100100;
const int mod = 1000000009;
int f[N];
int find(int x){ return x == f[x] ? x : f[x] = find(f[x]); }
bool Union(int x, int y){
	int fx = find(x), fy = find(y);
	if (fx == fy)return false;
	if (fx > fy)swap(fx, fy);
	f[fx] = fy;
	return true;
}
int n, m;
int main(){
	while (cin >> n >> m){
		for (int i = 1; i <= n; i++)f[i] = i;
		int ans = 1;
		while (m--){
			int u, v; scanf("%d %d", &u, &v);
			if (Union(u, v)==false)
				ans = (ans + ans) % mod;
			printf("%d\n", ans-1);
		}
	}
	return 0;
}
时间: 2024-08-23 17:52:40

Codeforces 91C Ski Base 加边求欧拉回路数量的相关文章

CodeForces 21D Traveling Graph 状压dp+欧拉回路

题目链接:点击打开链接 题意: 给定n个点m条边的无向图 求从1点开始经过每条边至少一次最后回到1点的最小路程 显然就是找一条路径可重复的欧拉回路 思路: 首先对于欧拉回路的结论是:所有点的度数都为偶数 因为所有边至少经过一次,那么可以把题意转换成加最少多少条边使得图满足以上结论 而加的边目的是为了把奇度数转成偶度数,先floyd一下得到任意点间加边的最小花费 dp[i]表示状态i下度数都为偶数的最小花费. 状压dp,把i状态下,所有未选择的点中挑2个奇度数的转移即可. #include <cs

UVa10054 The Necklace,无向图求欧拉回路

无向图求欧拉回路: 1.图连通 2.所有顶点的度数位偶数 随便从一个点开始递归遍历即可求出路径 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxcolor = 50; int n, G[maxcolor+1][maxcolor+1], deg[maxcolor+1]; struct Edge{ int from, to; Edge(int f

poj1041 John&#39;s trip,无向图求欧拉回路路径

点击打开链接 无向图求欧拉回路: 1.图连通 2.所有顶点的度数位偶数 #include <cstdio> #include <cstring> #include <stack> #include <queue> #include <algorithm> using namespace std; const int mt = 2000; const int ms = 50; bool vis[mt+5]; int g[ms][mt+5]; int

矩阵连乘 和表达式加括号求最大值

矩阵连乘核心代码1 for(int i=0;i<=n;i++) 2 m[i][j]=0; 3 for(r=1;r<n;r++) 4 for(i=1;i<=n-r;i++) 5 { 6 j=i+r; 7 m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j]; 8 s[i][j]=i; 9 for(k=i+1;k<j;k++) 10 { 11 int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; 12 if(t<m[i][j]) 13

hdu4612 连通性,求树的直径,加一边求最少桥

http://acm.hdu.edu.cn/showproblem.php?pid=4612 Problem Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels. If we can isolate

poj1041 John&#39;s trip (无向图求欧拉回路方案)

John's trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5950   Accepted: 1946   Special Judge Description Little Johnny has got a new car. He decided to drive around the town to visit his friends. Johnny wanted to visit all his frien

求图中欧拉回路数量

问题描述:输入点数n.边数m.每条边连接的两个点a,b,求此无向图中不包括一个点本身的欧拉回路数量,重复不计: 解决此问题,则需要在深搜的基础上判断新搜出的欧拉回路是否已经被走过,可以利用搜索时所打的标记来判断: 使用邻接表,需要注意在无向图中连接两点有两条边,要同时考虑: 以下为代码: #include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,m,cnt[105],ct,q

求细胞数量——dfs

最近重新回顾了一下dfs,于是就打了洛谷上"求细胞数量"这一题. 这题注意要在输入时是一个一个数字读取的,因为在输入矩阵的时候没有空格.我就随便改了一下快读. #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; int getin(){ int num=0; char c=getchar(); whil

求质数数量 - 空间换时间

质数:被自己本身和1整出的数 int getPrimeCount(int value){ int count = 0; int arr[301] = {0};// 0 - is prime , 1 - is not prime int num = (int)sqrt((float)value); for(int i = 2; i <= num ; ++i){ if (!arr[i]){ for(int j = i; i * j < value; ++j){ arr[i * j] = 1; }