摘要:hash 1 # include <stdio.h> 2 # include <string.h> 3 4 # define N 205 5 # define M 100007 6 7 typedef long long int LL; 8 9 int n;10 LL a[6][N];11 int head[M], next[N*N+N];12 13 int hash(LL x)14 {15 return ((x%M)+M)%M;16 }17 18 void init_hash_table(void)19 {20 memse...
阅读全文
摘要:最小表示法 + 排序 + 枚举, 整体复杂度:O(n*lgn*6)这道题普通的枚举就可以做,hash 和枚举差不多,繁琐的地方都在判断是否同构那里,我干脆用最小表示法把原串转换为原串的最小表示和反串的最小表示中的较小者,然后排序,枚举相邻的位置的串是否相等;最小表示法的一点更正:这篇博文中作者做了一个优化,我以前是参考优化后的做法写的,现在发现评论中有人提到了一个问题(最小位置直接出现在对升序序列后的情况下,这个优化实际上使复杂度变为了O(n^2),已经验证),把 j 减少到 i+1 不合理,所以又回到了原始的做法,具体见代码。# include <stdio.h># includ
阅读全文
摘要:二分:3+2;# include <stdio.h># include <stdlib.h># define trq(x) ((x)*(x)*(x))int a[5];long long ans = 0;int h[105];int f[305*105*105], g[305*105];/************************************************************/int cmp(const void *x, const void *y){ return *(int*)x - *(int*)y;}int bins(int *v
阅读全文
摘要:此题数据范围其实很小,枚举主对角线,求出另两个点的坐标,看是否存在(所有点都不相同);hash的模版写法:# include <stdio.h># include <string.h># define odd(x) (((x)+100000)&0x1)# define MAXN 1005# define MOD 10007int n;int x[MAXN], y[MAXN];int head[MOD], next[MAXN];int hash(int xx, int yy){ int hkey = xx*13131 + yy; return (hkey%MOD
阅读全文
摘要:题解;数组hash:hash的是排列,不能用相加、相乘取模,常用hash函数的资料; 1 # include <stdio.h> 2 # include <string.h> 3 4 # define get(x, i) ((((x)>>(i))&0x1) ? 1:0) 5 6 # define N 100005 7 # define K 35 8 # define MOD 100007 9 10 int sum[N][K], c[N][K], a[N], h[MOD << 3];11 12 int Max(int x, int y)13
阅读全文
摘要:每次查找第一个降序的首字符,如果不存在就删除结尾字符,链表,O(n)。# include <cstdio># include <iostream>using namespace std;struct node{ char ch; node *pre, *next;};void b(node *head, char *s){ head->ch = s[0]; node *tmp = head; for (int i = 0; s[i]; ++i) { node *cur = new node; cur->ch = s[i+1]; ...
阅读全文
摘要:判断最小生成树是否唯一,可以证明如果MST不唯一,必然是由于有两条边的权相等(反过来不成立),那么在第一次求MST时可以标记这类边,然后逐一去掉重新求MST,看是否和之前的相等。/* 判断最小生成树是否唯一, kruskal */# include <stdio.h># include <stdlib.h># define N 105# define M 5005int n, m;int p[N];int r[M], u[M], v[M], w[M];char h[M], ud[M], pi[M];int find(int x) {return x==p[x] ? x:
阅读全文
摘要:状态转移方程p[i,j] = 0.5*(p[i-1,j]+p[i,j-1])。浮点数运算,初始时要向上取整。# include <stdio.h># include <math.h># include <string.h>int ap1, ap2, hp1, hp2;double f[1005][1005];double cal(int x, int y){ if (f[x][y] >= 0) return f[x][y]; if (x <= 0) return f[x][y] = 0; if (y <= 0) return f[x][y]
阅读全文
摘要:targan算法。 1 # include <cstdio> 2 # include <cstring> 3 4 # define N (1000 + 5) 5 6 int n, son, tmpdfn; 7 int low[N], dfn[N], subnets[N]; 8 char g[N][N]; 9 10 int Min(int x, int y)11 {12 return x<y ? x:y;13 }14 15 void tarjan(int u, int r)16 {17 dfn[u] = low[u] = ++tmpdfn;18 for (int v
阅读全文
摘要:和每日一题一样,只不过是给出每个顶点的邻接点,这里使用邻接表来做。 1 # include <cstdio> 2 # include <cstring> 3 4 # define N (100 + 5) 5 # define M ((N) * (N)) 6 7 int n, m; 8 int top, cols, tmpdfn; 9 int c[N], in[N], out[N], low[N], dfn[N], first[N], s[N]; 10 int u[M], v[M], next[M]; 11 char ins[N]; 12 13 int Min(int x
阅读全文
摘要:prim入门练习题。prim的流程如下:// 清空顶点集;任选一个点u作为起点,加入顶点集,从u出发选一条最小边(u, v),将v加入顶点集,重复直到所有点都进入顶点集。其中最小边可以用堆来做,还可以用邻接表加速(这里嫌麻烦)。 1 # include <cstdio> 2 # include <queue> 3 4 using namespace std; 5 6 typedef pair<int, int> pii; 7 8 # define N (100 + 5) 9 # define INF 0x7FFFFFFF10 11 int n;12 int
阅读全文
摘要:tarjan算法的思路不难理解,用low来标记同一个强联通分量中的点,初始时low[i]=dfn[i],当访问到已经在当前栈中的顶点时,相当于找到了一个强联通分量的根节点(一个强联通分量中最早访问到的作为根节点),然后递归地更新栈中所有节点,如果遇到low[k]=dfn[k],说明k就是这个分量的根,于是对之前的所有点出栈并标记(此处标记用连续的值1,2,3代表第几个强联通分量,其实可以直接用low就行,cols记录强联通分量的个数)。 1 # include <cstdio> 2 # include <cstring> 3 4 # define N (100 + 5)
阅读全文
摘要:模版,注意使用int可能在求叉乘的过程中溢出,解决办法:使用double(使用int在在返回时只返回符号有时也可以);使用double的:# include <cmath>const double eps = 1e-8;struct Point{double x, y;} ;int dcmp(double x){ if (fabs(x) < eps) return 0; return x>0 ? 1:-1;}int direction(Point p1, Point p2, Point p3){ double tmp = (p3.x-p1.x)*(p2.y-p1.y)
阅读全文
摘要:N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输。问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。问题2:至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。input format:输入有多组样例,大约1000组。每组样例第一行包含两个整数N,M(2<=N<=100),N代表学校的个数,M代表边的个数(M<N*N)接下来M行,每行包含连个整数u,v,代表u可以向v单向发送数据。output format每组样例对应两行,分别是问题一和问题二的解。sam
阅读全文
摘要:这道题直接模拟即可,DP相当于一个优化,记录下从第i行第j列出发后到达的最终位置,下次需要时直接取,优化前后最坏情况下复杂度都是O(10^6)。# include <cstdio># include <cstring> # define N 1000 + 5 int n, m;int cnt[N], ff[N], f[N][N];char g[N][N]; int down(int row, int col){ int &ans = f[row][col]; if (ans != -1) return ans; if (row == n) return ans
阅读全文
摘要:两边DFS求强联通分支,缩点;算法流程:dfs(G);dfs(G') in the order which f[] decreases. output tree in the dfs forest as a strongly connected component第一遍DFS为每个顶点打上时间戳,第二遍是反向DFS,按照时间戳递减的顺序访问每个结点,原图中的边作为反向边进行遍历,此时对于强联通分量必定是可以通过其中任一个点访问到,而原图中时间戳较晚(较早访问到的,注意加时间戳的位置)但不属于某个强联通分量的顶点必然到某个强联通分量有一条单向边,反向DFS时由于原边方向改变,无法通过这条
阅读全文
摘要:拓扑排序判断有向图是否有环,1A啊!!!对每个位置(前3行前3列),如果它控制范围内的某个位置上为 j ,而这个位置原始值为 i ,则添加一条 i 到 j 的边,如果出现环则说明电脑出问题了;不知道数据中是否含有非法的,所以就加了个判断:判断是否出现了非法状态,即某个位置出现了不属于这个位置的数字。# include <cstdio># include <cstring># define N 5# define NS ((N-1)*(N-1)) + 1const int n = 3;const int m = 9;int in[NS];int f[N][N];char
阅读全文
摘要:第一道拓扑排序,拓扑排序的过程很简单:每次拿出一个入度为0的顶点放入solu[]尾部,并将它可以直接到达的顶点的入度减1;对这道题需要得到唯一顺序,每次发现有多个入度为0的顶点时,说明还未排好序,此时不应该直接返回cannot be determined而是对所有入度为0的顶点执行上述操作,如果发现到某一步没有入度为0的顶点了说明出现矛盾,此时返回出现矛盾;PS:这道题的输入有重复。# include <cstdio># include <cstring># define N 26 + 1int n, m;int in[N], tmp[N];char ans[N], g
阅读全文
摘要:和COJ送货到家一样,不过这里不要求每个点只经过一次,因此可以先用floyd预处理出任意两点间的最短距离,然后状态压缩DP。# include <cstdio># include <cstring># define INF 0x3C3C3C3C# define N 10 + 2int n;int w[N][N];int f[1<<N][N];int Min(int x, int y){ return x<y ? x:y;}int dp(int s, int i){ int &ans = f[s][i]; if (ans != -1) retur
阅读全文
摘要:// 编辑距离的方法可以水过这道题编辑距离的计算方法即一个不完全的证明见:http://en.wikipedia.org/wiki/Levenshtein_distance具体如下图:# include <cstdio># include <cstring># define LEN 10 + 2# define N 1500 + 5int n, m;char s[LEN];int len[N];char dic[N][LEN];int Abs(int x){ return x>0 ? x:-x;}int Min(int x, int y, int z){ int
阅读全文