复习计划
明天要考试啦今天就扫一扫以前的模板吧
感觉有点方
字符串
1.AC自动机
cogs1913裸题
#include <bits/stdc++.h> using namespace std; char str[12][100], s[10000010]; int n, cnt; int t[1000][26], fail[1000]; int is[1000]; struct Edge { int to, nxt; }edge[10010]; int h[1000], edges; void addedge(int u, int v) { ++ edges; edge[edges].to = v; edge[edges].nxt = h[u]; h[u] = edges; } void insert(char* str, int pos) { int nw = 0, n = strlen(str+1); for(int i = 1; i <= n; ++ i) { int c = str[i]-'a'; if(t[nw][c] == -1) t[nw][c] = ++ cnt, nw = cnt; else nw = t[nw][c]; } is[nw] = pos; } int que[1000], head, tail; void buildfail() { for(int i = 0; i < 26; ++ i) if(t[0][i] == -1) t[0][i] = 0; else que[tail ++] = t[0][i], fail[t[0][i]] = 0; while(head != tail) { int u = que[head ++]; for(int i = 0; i < 26; ++ i) { if(t[u][i] == -1) t[u][i] = t[fail[u]][i]; else fail[t[u][i]] = t[fail[u]][i], que[tail ++] = t[u][i]; } } for(int i = 1; i <= cnt; ++ i) addedge(fail[i], i); } int dfs_clock, dfn[1000]; bool vis[1000]; void dfs(int u) { dfn[++ dfs_clock] = u; vis[u] = true; for(int i = h[u]; i; i = edge[i].nxt) { int v = edge[i].to; if(!vis[v]) dfs(v); } } int num[1000], ans[12]; int main() { freopen("ACautomata.in","r",stdin); freopen("ACautomata.out","w",stdout); scanf("%d", &n); memset(t, -1, sizeof t); for(int i = 1; i <= n; ++ i) { scanf("%s", str[i]+1); insert(str[i], i); } buildfail(); dfs(0); scanf("%s", s+1); int len = strlen(s+1), nw = 0; for(int i = 1; i <= len; ++ i) { nw = t[nw][s[i]-'a']; num[nw] ++; } for(int i = dfs_clock; i; -- i) num[fail[dfn[i]]] += num[dfn[i]]; for(int i = 1; i <= cnt; ++ i) if(is[i]) ans[is[i]] = num[i]; for(int i = 1; i <= n; ++ i) printf("%s %d\n", str[i]+1, ans[i]); return 0; }
2.后缀自动机
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define maxn 100010 using namespace std; char s[maxn], c[maxn]; struct Node { int len, link, nxt[26]; } st[maxn << 1]; int size, root, last; void init() { size = root = last = 0; st[root].link = -1; st[root].len = 0; } void Extend(char ch) { int cur = ++ size; int p, c = ch-'a'; st[cur].len = st[last].len+1; for(p = last; ~p && st[p].nxt[c] == 0; p = st[p].link) st[p].nxt[c] = cur; if(p == -1) st[cur].link = root; else { int q = st[p].nxt[c]; if(st[p].len+1 == st[q].len) st[cur].link = q; else { int clone = ++ size; st[clone] = st[q]; st[clone].len = st[p].len+1; for(; ~p && st[p].nxt[c] == q; p = st[p].link) st[p].nxt[c] = clone; st[q].link = st[cur].link = clone; } } last = cur; } int main() { scanf("%s%s", s+1, c+1); int n = strlen(s+1), m = strlen(c+1); init(); for(int i = 1; i <= n; ++ i) Extend(s[i]); int now = root, step = 0, ans = 0; for(int i = 1; i <= m; ++ i) { int p = c[i]-'a'; if(st[now].nxt[p]) now = st[now].nxt[p], step ++; else { for(; ~now && !st[now].nxt[p]; now = st[now].link); if(now == -1) now = root, step = 0; else { step = st[now].len+1; now = st[now].nxt[p]; } } ans = max(ans, step); } printf("%d\n", ans); return 0; }
图论
1.二分图最大匹配
BZOJ1191 超级英雄Hero
g[], vis[], tim
#include<bits/stdc++.h> #define maxn 10010 using namespace std; int n, m; struct Edge { int to, nxt; }edge[100010]; int h[maxn], cnt; void addedge(int u, int v) { ++ cnt; edge[cnt].to = v; edge[cnt].nxt = h[u]; h[u] = cnt; } int g[maxn], vis[maxn], tim; bool find(int u) { vis[u] = tim; for(int i = h[u]; i; i = edge[i].nxt) { int v = edge[i].to; if(vis[v] == tim) continue; vis[v] = tim; if(g[v] == 0 || find(g[v])) { g[v] = u; g[u] = v; return true; } } return false; } int main() { scanf("%d%d", &n, &m); int u, v; for(int i = 1; i <= m; ++ i) { scanf("%d%d", &u, &v); u += m+1; v += m+1; addedge(i, u); addedge(u, i); addedge(i, v); addedge(v, i); } int ans = 0; for(int i = 1; i <= m; ++ i) if(!g[i]) { ++ tim; if(find(i)) ans ++; else break; } printf("%d\n", ans); return 0; }
2.强联通分量
cogs908 校园网
low[], pre[], sccno[], dfs_clock, scc_cnt
注意区分强联通分量的编号和具体点的编号
#include<bits/stdc++.h> #define maxn 105 using namespace std; int n; struct Edge { int to, nxt; }edge[maxn*maxn*2]; int h[maxn], cnt; void addedge(int u, int v) { ++ cnt; edge[cnt].to = v; edge[cnt].nxt = h[u]; h[u] = cnt; } stack<int> sta; int sccno[maxn], low[maxn], pre[maxn]; int dfs_clock, scc_cnt; void Tarjan(int u) { sta.push(u); pre[u] = low[u] = ++ dfs_clock; for(int i = h[u]; i; i = edge[i].nxt) { int v = edge[i].to; if(!pre[v]) Tarjan(v), low[u] = min(low[u], low[v]); else if(!sccno[v]) low[u] = min(low[u], pre[v]); } if(low[u] == pre[u]) { ++ scc_cnt; for( ; ;) { int v = sta.top(); sta.pop(); sccno[v] = scc_cnt; if(v == u) break; } } } int in[maxn], out[maxn]; int main() { freopen("schlnet.in","r",stdin); freopen("schlnet.out","w",stdout); scanf("%d", &n); int x; for(int i = 1; i <= n; ++ i) while(scanf("%d", &x) && x) addedge(i, x); for(int i = 1; i <= n; ++ i) if(!sccno[i]) Tarjan(i); for(int u = 1; u <= n; ++ u) { for(int i = h[u]; i; i = edge[i].nxt) { int v = edge[i].to; if(sccno[u] != sccno[v]) ++ in[sccno[v]], ++ out[sccno[u]]; } } if(scc_cnt == 1) { printf("1\n0\n"); return 0; } int ans1 = 0, ans2 = 0; for(int i = 1; i <= scc_cnt; ++ i) { if(!in[i]) ++ ans1; if(!out[i]) ++ ans2; } printf("%d\n%d\n", ans1, max(ans1, ans2)); return 0; }
3.最大流
cogs草地排水
#include <bits/stdc++.h> using namespace std; int n, m, S, T; struct Edge { int to, nxt, w; }edge[10100]; int h[500], cnt; void addedge(int u, int v, int w) { ++ cnt; edge[cnt].to = v; edge[cnt].nxt = h[u]; edge[cnt].w = w; h[u] = cnt; swap(u, v), w = 0; ++ cnt; edge[cnt].to = v; edge[cnt].nxt = h[u]; edge[cnt].w = w; h[u] = cnt; } const int inf = 0x7fffffff; int que[500], d[500]; bool bfs() { int head = 0, tail = 0; memset(d, -1, sizeof d); d[S] = 0; que[tail ++] = S; while(head != tail) { int u = que[head ++]; for(int i = h[u]; i; i = edge[i].nxt) { if(!edge[i].w) continue; int v = edge[i].to; if(d[v] == -1) { d[v] = d[u]+1; que[tail ++] = v; } } } return d[T] != -1; } int dfs(int x, int a) { if(x == T || a == 0) return a; int used = 0, f; for(int i = h[x]; i; i = edge[i].nxt) { int v = edge[i].to; if(d[v] == d[x]+1) { f = dfs(v, min(a-used, edge[i].w)); edge[i].w -= f; edge[i^1].w += f; used += f; if(a == used) return a; } } if(used == 0) d[x] = -1; return used; } int Dinic() { int ret = 0; while(bfs()) ret += dfs(S, inf); return ret; } int main() { scanf("%d%d", &m, &n); cnt = 1; S = 1, T = n; int u, v, w; for(int i = 1; i <= m; ++ i) { scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); } printf("%d\n", Dinic()); return 0; }
4.费用流
#include <bits/stdc++.h> #define maxn 5000 using namespace std; int n, p, s; int a[maxn], b[maxn]; struct Edge { int to, nxt, w, dis; }edge[500010]; int h[maxn], cnt, S, T; void addedge(int u, int v, int w, int dis) { ++ cnt; edge[cnt].w = w; edge[cnt].to = v; edge[cnt].dis = dis; edge[cnt].nxt = h[u]; h[u] = cnt; swap(u, v), w = 0, dis = -dis; ++ cnt; edge[cnt].w = w; edge[cnt].to = v; edge[cnt].dis = dis; edge[cnt].nxt = h[u]; h[u] = cnt; } #define A n+1 #define B n+2 const int inf = 0x7fffffff/2; int ans; int dis[maxn], from[maxn]; bool vis[maxn]; queue<int> Q; bool Spfa() { for(int i = S; i <= T; ++ i) dis[i] = inf; dis[S] = 0; int head = 0, tail = 0; Q.push(S); while(!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = false; for(int i = h[u]; i; i = edge[i].nxt) { if(edge[i].w) { int v = edge[i].to; if(dis[v] > dis[u] + edge[i].dis) { dis[v] = dis[u] + edge[i].dis; from[v] = i; if(!vis[v]) { vis[v] = true; Q.push(v); } } } } } int x = inf; for(int i = from[T]; i; i = from[edge[i^1].to]) x = min(x, edge[i].w); for(int i = from[T]; i; i = from[edge[i^1].to]) ans += x*edge[i].dis, edge[i].w -= x, edge[i^1].w += x; return dis[T] < inf; } vector<int> G; int main() { cnt = 1; scanf("%d%d%d", &n, &p, &s); for(int i = 1; i <= n; ++ i) scanf("%d", &a[i]); for(int i = 1; i <= n; ++ i) scanf("%d", &b[i]); S = 0, T = n+3; for(int i = 1; i <= n; ++ i) { addedge(S, i, 1, 0); addedge(i, A, 1, -a[i]); addedge(i, B, 1, -b[i]); } addedge(A, T, p, 0); addedge(B, T, s, 0); while(Spfa()); printf("%d\n", -ans); for(int i = h[A]; i; i = edge[i].nxt) if(edge[i].w == 1) G.push_back(edge[i].to); sort(G.begin(), G.end()); for(int i = 0; i < G.size(); ++ i) printf("%d ", G[i]); printf("\n"); G.clear(); for(int i = h[B]; i; i = edge[i].nxt) if(edge[i].w == 1) G.push_back(edge[i].to); sort(G.begin(), G.end()); for(int i = 0; i < G.size(); ++ i) printf("%d ", G[i]); return 0; }
5.KM算法
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define maxn 305 using namespace std; int n; int G[maxn][maxn]; int Cx[maxn], Cy[maxn], linky[maxn], slack[maxn]; bool visx[maxn], visy[maxn]; bool dfs(int u) { visx[u] = true; for(int v = 1; v <= n; ++ v) { if(visy[v]) continue; int diffenerce = Cx[u]+Cy[v]-G[u][v]; if(diffenerce == 0) { visy[v] = true; if(linky[v] == 0 || dfs(linky[v])) { linky[v] = u; return true; } } else slack[v] = min(slack[v], diffenerce); } return false; } int KM() { memset(Cx, 0, sizeof Cx); memset(Cy, 0, sizeof Cy); memset(linky, 0, sizeof linky); for(int i = 1; i <= n; ++ i) { Cx[i] = G[i][1]; for(int j = 2; j <= n; ++ j) Cx[i] = max(Cx[i], G[i][j]); } for(int i = 1; i <= n; ++ i) { memset(slack, 0x7f, sizeof slack); while(true) { memset(visx, 0, sizeof visx); memset(visy, 0, sizeof visy); if(dfs(i)) break; int d = 0x7fffffff; for(int j = 1; j <= n; ++ j) if(!visy[j]) d = min(d, slack[j]); for(int j = 1; j <= n; ++ j) { if(visx[j]) Cx[j] -= d; if(visy[j]) Cy[j] += d; else slack[j] -= d; } } } int res = 0; for(int i = 1; i <= n; ++ i) res += G[linky[i]][i]; return res; } int main() { while(scanf("%d", &n) != EOF) { for(int i = 1; i <= n; ++ i) for(int j = 1; j <= n; ++ j) scanf("%d", &G[i][j]); printf("%d\n", KM()); } return 0; }
因自己的小错误
然后考试就炸了。。罚时超多
比较印象深刻的是考了trie,字符串处理,凸包(想着复习计算几何但是没有复习但是还是写出来了!),最小生成树等等
比较基础吧,主要是读英文题有点费劲
第25名不知道能不能进实验班
给时光以生命,而不是给生命以时光。