明天要考试啦今天就扫一扫以前的模板吧
感觉有点方
字符串
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名不知道能不能进实验班