ソースを参照

add Shendan's codes

Olivier Marty 8 年 前
コミット
b85e595190
9 ファイル変更314 行追加0 行削除
  1. 38 0
      code/2SAT.cpp
  2. 58 0
      code/BCC.cpp
  3. 19 0
      code/Binom.cpp
  4. 17 0
      code/BipartiteTest.cpp
  5. 31 0
      code/CutVertexBridge.cpp
  6. 26 0
      code/EulerCircuit.cpp
  7. 83 0
      code/ExactCover.cpp
  8. 18 0
      code/Primes.cc
  9. 24 0
      main.tex

+ 38 - 0
code/2SAT.cpp

@@ -0,0 +1,38 @@
+struct TwoSAT {
+	int n;
+	VI G[maxn*2];
+	bool mark[maxn*2];
+	int S[maxn*2], c;
+	bool dfs(int x) {
+		if (mark[x^1]) return false;
+		if (mark[x]) return true;
+		mark[x] = true;
+		S[c++] = x;
+		for (int i = 0 ; i < G[x].size(); i++)
+			if (!dfs(G[x][i])) return false;
+		return true;
+	}
+	void init(int n) {
+		this->n = n;
+		for (int i = 0; i < n*2; i++) G[i].clear();
+		memset(mark, 0, sizeof(mark));
+	}
+	//x =xval or y = yval
+	void add_clause(int x, int xval, int y ,int yval) {
+		x = x * 2 + xval;
+		y = y * 2 + yval;
+		G[x^1].push_back(y);
+		G[y^1].push_back(x);
+	}
+	bool solve() {
+		for (int i = 0; i < n * 2; i += 2)
+			if (!mark[i] && !mark[i+1]){
+				c = 0;
+				if (!dfs(i)){
+					while (c > 0) mark[S[--c]] = false;
+					if (!dfs(i+1)) return false;
+				}
+			}
+		return true;
+	}
+};

+ 58 - 0
code/BCC.cpp

@@ -0,0 +1,58 @@
+//Find the biconnected component in the undirected graph.
+//It means that, for all (x,y), there are at least two ways from u to y using the different nodes.
+//Remark:  every edge belongs to the one of the bcc.
+//		   two different bcc may have au most one common node (the cut vertex)
+// 		   
+//For the edge-bcc :
+// delete all the bridges, every cc is a bcc in the original graph.
+int pre[maxn], iscut[maxn], bccno[maxn], dfs_clock, bcc_cnt;
+vector<int> G[maxn], bcc[maxn];
+struct Edge{
+	int u, v;
+	Edge(int uu, int vv): u(uu), v(vv) {}
+};
+stack<Edge> S;
+int dfs(int u, int fa) {
+	int lowu = pre[u] = ++dfs_clock;
+	int child = 0;
+	for (int i = 0; i < G[u].size(); i++){
+		int v = G[u][i];
+		Edge e = (Edge){u, v};
+		if (!pre[v]) {
+			S.push(e);
+			child ++;
+			int lowv = dfs(v, u);
+			lowu = min(lowu, lowv);
+			if (lowv >= pre[u]) {
+				iscut[u] = true;
+				bcc_cnt++; bcc[bcc_cnt].clear();
+				for (;;){
+					Edge x = S.top(); S.pop();
+					if (bccno[x.u] != bcc_cnt) {
+						bcc[bcc_cnt].push_back(x.u);
+						bccno[x.u] = bcc_cnt;
+					}
+					if (bccno[x.v] != bcc_cnt) {
+						bcc[bcc_cnt].push_back(x.v);
+						bccno[x.v] = bcc_cnt;
+					}
+					if (x.u == u && x.v == v) break;
+				}
+			}
+		}
+		else if (pre[v] < pre[u] && v != fa){
+			S.push(e);
+			lowu = min(lowu, pre[v]);
+		}
+	}
+	if (fa < 0 && child == 1) iscut[u] = 0;
+	return lowu;
+}
+void find_bcc(int n) {
+	memset(pre, 0, sizoef(pre));
+	memset(iscut, 0, sizeof(iscut));
+	memset(bccno, 0, sizoef(bccno));
+	dfs_clock = bcc_cnt = 0;
+	for (int i = 0; i < n; i++)
+		if (!pre[i]) dfs(i, -1);
+}

+ 19 - 0
code/Binom.cpp

@@ -0,0 +1,19 @@
+/*
+	C(n,k) + C(n,k+1) = C(n+1, k+1)
+
+	C(n,k+1) = C(n,k) * (n-k)/(k+1)
+*/
+//Calculer c[n][k] for all k <= m.
+int coeff_bin1(int n, int m){
+	c[n][0] = 1;
+	for (int k = 0; k < m; k++)
+		c[n][k + 1] = c[n][k] * (n-k)/(k+1);
+}
+//Calculer tout
+void coeff_bin2(int n, int m){
+	memset(c, 0, sizeof(c));
+	for (int i = 0; i <= n; i++) c[i][0] = 1;
+	for (int i = 1; i <= n; i++)
+		for (int j = 1; j <= m; j++)
+			c[i][j] = c[i-1][j] + c[i-1][j-1];
+}

+ 17 - 0
code/BipartiteTest.cpp

@@ -0,0 +1,17 @@
+//O(m);
+//check if the connected component of u is a bipartite graph.
+//color : 1 or 2.  0 for uncolored.
+// initially : memset(color, 0, sizeof(color));
+int color[maxn];
+VI G[maxn];
+bool bipartite(int u) {
+	for (int i = 0; i < G[u].size(); i++) {
+		int v = G[u][i];
+		if (color[v] == color[u]) return false;
+		if (!color[v]) {
+			color[v] = 3 - color[u];
+			if (!bipartite(v)) return false;
+		}
+	}
+	return true;
+}

+ 31 - 0
code/CutVertexBridge.cpp

@@ -0,0 +1,31 @@
+int dfs_clock = 0;
+int iscut[maxn];
+int low[maxn], pre[maxn];
+//appeler: dfs(u, -1).
+//Initialisation:
+//	memset(pre, 0, sizeof(pre));
+//	memset(iscut, false, sizeof(iscut);
+//Complexite: O(n+m)
+int dfs(int u, int fa){ // u's father is fa.
+	int lowu = pre[u] = ++dfs_clock;
+	int child = 0;
+	for (int i = 0; i < G[u].size(); i++){
+		int v = G[u][i];
+		if (!pre[v]) {
+			child ++;
+			int lowv =dfs(v, u);
+			lowu = min(lowu, lowv);
+			//if (lowv > pre[u]) { isbridge[u][v] = true; }
+			if (lowv >= pre[u]){
+				iscut[u] = true;
+			}
+		}
+		else if (pre[v] < pre[u] && v != fa){
+			lowu = min(lowu, pre[v]);
+		}
+	}
+
+	if (fa < 0 && child == 1) iscut[u] = 0;
+	low[u] = lowu;
+	return lowu;
+}

+ 26 - 0
code/EulerCircuit.cpp

@@ -0,0 +1,26 @@
+struct Edge {
+  int from, to;
+  Edge(int from, int to):from(from),to(to) {}
+};
+int n; // nombre de sommets.
+int G[maxn][maxn]; // G[i][j]= # d'aretes i->j
+int deg[i];
+vector<Edge> ans; // resultat.
+void euler(int u){
+  	for(int v = 1; v <= n; v++) if(G[u][v]) {
+    	G[u][v]--; G[v][u]--; //only G[u][v]--; for directed graph.
+    	euler(v);
+    	ans.push_back(Edge(u, v));
+  	}
+}
+int solve_euler_path() {
+ 	bool solved = true;
+ 	for(int i = 1; i <= n; i++)
+ 		if(deg[i] % 2 == 1) { solved = false; break; } 
+ 		if(solved) {
+      		ans.clear();
+      		euler(start);
+      		if(ans.size() != n || ans[0].to != ans[ans.size()-1].from) solved = false;
+    	}
+    return solved;
+}

+ 83 - 0
code/ExactCover.cpp

@@ -0,0 +1,83 @@
+const int maxn = 1000;
+const int maxnode = 1000;
+const int maxr = 1000;
+// l'algorithme X + Dancing links.
+struct DLX {
+  int n, sz; //nb de colonne, nb de noeuds.
+  int S[maxn]; //nb de noeuds dans chaque colonne.
+  int row[maxnode], col[maxnode]; // index de ligne et colonne pour chaque noeud.
+  int L[maxnode], R[maxnode], U[maxnode], D[maxnode];
+  int ansd, ans[maxr]; //solution
+  void init(int n) {
+    this->n = n;
+    // noeud virtuel
+    for(int i = 0 ; i <= n; i++) {
+      U[i] = i; D[i] = i; L[i] = i-1, R[i] = i+1;
+    }
+    R[n] = 0; L[0] = n;
+    sz = n + 1;
+    memset(S, 0, sizeof(S));
+  }
+  void addRow(int r, VI columns) {
+    int first = sz;
+    for(int i = 0; i < columns.size(); i++) {
+      int c = columns[i];
+      L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];
+      D[U[c]] = sz; U[c] = sz;
+      row[sz] = r; col[sz] = c;
+      S[c]++; sz++;
+    }
+    R[sz - 1] = first; L[first] = sz - 1;
+  }
+  #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i])
+  void remove(int c) {
+    L[R[c]] = L[c];
+    R[L[c]] = R[c];
+    FOR(i,D,c)
+      FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
+  }
+  void restore(int c) {
+    FOR(i,U,c)
+      FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
+    L[R[c]] = c;
+    R[L[c]] = c;
+  }
+  bool dfs(int d) { //d : depth
+    if (R[0] == 0) { // Found the solution
+      ansd = d; // the length of the solution
+      return true;
+    }
+    // Find the column c which has the minimum S.
+    int c = R[0]; //the first column non-deleted
+    FOR(i,R,0) if(S[i] < S[c]) c = i;
+    remove(c);
+    FOR(i,D,c) {
+      ans[d] = row[i];
+      FOR(j,R,i) remove(col[j]); //Delete all columns covered by i-th line.
+      if(dfs(d+1)) return true;
+      FOR(j,L,i) restore(col[j]); // Undo
+    }
+    restore(c);
+    return false;
+  }
+  bool solve(VI& v) {
+    v.clear();
+    if(!dfs(0)) return false;
+    for(int i = 0; i < ansd; i++) v.push_back(ans[i]);
+    return true;
+  }
+};
+void test() {
+  DLX solver;
+  solver.init(7);
+  // parmi ces 6 ensembles, existe-t-il une couverture exacte de 1..7?
+  VI v1 = {1,4,7}; VI v2 = {1,4}; VI v3 = {4,5,7};
+  VI v4 = {3,5,6}; VI v5 = {2,3,6,7}; VI v6 = {2,7};
+  solver.addRow(1, v1); solver.addRow(2, v2); solver.addRow(3, v3); solver.addRow(4, v4); solver.addRow(5, v5); solver.addRow(6, v6);
+  VI ans;
+  solver.solve(ans);
+  for (int i = 0; i < ans.size(); i++)
+    cout<< ans[i] << endl;
+  if (ans.size() == 0)
+    cout << "Non solution" <<endl;
+}

+ 18 - 0
code/Primes.cc

@@ -11,6 +11,24 @@ bool IsPrimeSlow (LL x)
   }
   return true;
 }
+// sieve
+const int maxn = 10000005;
+const int maxp = 700000;
+int vis[maxn]; //0 for prime number
+int prime[maxp];
+void sieve(int n){
+	int m = (int)sqrt(n+0.5);
+	memset(vis, 0, sizeof(vis));
+	for (int i = 2; i <= m, i++) if (!vis[i])
+		for (int j = i*i; j <= n; j += i) vis[j] = 1;
+}
+int gen_primes(int n) {
+	sieve(n);
+	int c = 0;
+	for (int i = 2; i <= n; i++) if (!vis[i])
+		prime[c++] = i;
+	return c;
+}
 // Primes less than 1000:
 //   2    3    5    7   11   13   17   19   23   29   31   37
 //  41   43   47   53   59   61   67   71   73   79   83   89

+ 24 - 0
main.tex

@@ -191,5 +191,29 @@ Temps de cuisson : $O(n)$
 \subsection{Skeleton}
 {\scriptsize\lstinputlisting{code/Skeleton.cpp}}
 
+\section{Oppa Shendan Style}
+
+\subsection{Eulerian Circuit}
+{\scriptsize\lstinputlisting{code/EulerCircuit.cpp}}
+
+\subsection{Test Bipartite Graph}
+{\scriptsize\lstinputlisting{code/BipartiteTest.cpp}}
+
+\subsection{Cut vertex / Bridge}
+{\scriptsize\lstinputlisting{code/CutVertexBridge.cpp}}
+
+\subsection{Biconnected component}
+{\scriptsize\lstinputlisting{code/CutVertexBridge.cpp}}
+
+\subsection{2 SAT}
+{\scriptsize\lstinputlisting{code/2SAT.cpp}}
+
+\subsection{Binomial coefficient}
+{\scriptsize\lstinputlisting{code/Binom.cpp}}
+
+\subsection{Exact Cover}
+{\scriptsize\lstinputlisting{code/ExactCover.cpp}}
+
+
 \end{multicols}
 \end{document}