最近水的一些模板题
KMP: 洛谷P3375
https://www.luogu.org/problem/show?pid=3375
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
const int MAXN = (int)1e6, MAXM = 1000;
char s1[MAXN + 10], s2[MAXM + 10];
inline void read(char *str)
{
char c;
int len = 0;
while(!isgraph(c = getchar()));
while(isgraph(c))
str[len++] = c, c = getchar();
}
inline void print(int x)
{
static int ans[10], top = 0;
if(x == 0)
putchar('0');
while(x)
ans[top ++] = x % 10, x /= 10;
while(top)
putchar(ans[-- top] + '0');
}
int pre[MAXN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("L3375.in", "r", stdin);
freopen("L3375.out", "w", stdout);
#endif
read(s1), read(s2);
int len2 = strlen(s2), p = - 1;
pre[0] = - 1;
for(int i = 1; i < len2; i ++)
{
while(p != - 1 && s2[p + 1] != s2[i])
p = pre[p];
p += (s2[p + 1] == s2[i]);
pre[i] = p;
}
int len1 = strlen(s1);
p = - 1;
for(int i = 0; i < len1; i ++)
{
while(p != - 1 && s1[i] != s2[p + 1])
p = pre[p];
p += (s2[p + 1] == s1[i]);
if(p + 1 == len2)
print(i - len2 + 2), putchar('
'), p = pre[p];
}
for(int i = 0; i < len2; i ++)
print(pre[i] + 1), putchar(' ');
}
网络流: 洛谷P3376
https://www.luogu.org/problem/show?pid=3376
△这里注意一下, 输出优化要特判0和负数的情况
#include<cstdio>
#include<cctype>
#include<cstring>
#include<climits>
#include<algorithm>
using namespace std;
inline void read(int &x)
{
char c;
x = 0;
int flag = 1;
while(! isgraph(c = getchar()))
if(c == '-')
flag *= - 1;
while(isgraph(c))
x = x * 10 + c - '0', c = getchar();
x *= flag;
}
const int maxN = (int)1e4, maxM = (int)1e5;
struct edge
{
int v, w, next;
}G[(maxM << 1) + 64];
int top;
int head[maxN + 64];
inline void addEdge(int u, int v, int w)
{
G[top].v = v;
G[top].w = w;
G[top].next = head[u];
head[u] = top ++;
}
int Q[maxN + 64];
int dep[maxN + 64];
inline int BFS(int s, int t)
{
int L = 0, R = 1;
Q[L] = s;
memset(dep, - 1, sizeof(dep));
dep[s] = 0;
while(L < R)
{
int u = Q[L];
for(int i = head[u]; i != - 1; i = G[i].next)
if(dep[G[i].v] == - 1 && G[i].w)
dep[G[i].v] = dep[u] + 1, Q[R ++] = G[i].v;
L ++;
}
return (dep[t] == - 1) ? 0 : 1;
}
inline int DFS(int u, int flow, int t)
{
if(u == t)
return flow;
int flow_sum = 0;
for(int i = head[u]; i != - 1; i = G[i].next)
{
int v = G[i].v;
if(G[i].w && dep[v] == dep[u] + 1)
{
int cur_flow = min(G[i].w, flow - flow_sum);
cur_flow = DFS(v, cur_flow, t);
flow_sum += cur_flow;
G[i].w -= cur_flow;
G[i ^ 1].w += cur_flow;
}
}
if(! flow_sum) //这一句可以优化很多
dep[u] = - 1;
return flow_sum;
}
void print(int x)
{
if(x < 0)
putchar('-'), x *= - 1;
if(x == 0)
putchar('0');
int ans[10], top = 0;
while(x)
ans[top ++] = x % 10, x /= 10;
for(; top; top --)
putchar(ans[top - 1] + '0');
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("L3376.in", "r", stdin);
freopen("L3376.out", "w", stdout);
#endif
int n, m, s, t;
read(n), read(m), read(s), read(t);
memset(head, - 1, sizeof(head));
top = 0;
for(int i = 0; i < m; i ++)
{
int u, v, w;
read(u), read(v), read(w);
addEdge(u, v, w);
addEdge(v, u, 0);
}
int flow = 0;
while(BFS(s, t))
while(int tmp = DFS(s, INT_MAX, t))
flow += tmp;
print(flow);
}
最小费用最大流: 洛谷P3381
https://www.luogu.org/problem/show?pid=3381
#include<cstdio>
#include<cctype>
#include<cstring>
#include<queue>
#include<climits>
using namespace std;
inline void read(int &x)
{
char c;
int flag = 1;
x = 0;
while(! isgraph(c = getchar()))
if(c == '-')
flag *= - 1;
while(isgraph(c))
x = x * 10 + c - '0', c = getchar();
x *= flag;
}
const int MAXN = 5000;
const int MAXM = (int)5e4;
int top;
struct edge
{
int v, w, cost, next;
}G[(MAXM << 1) + 64];
int head[MAXN + 64];
inline void addEdge(int u, int v, int w, int cost)
{
G[top].v = v;
G[top].w = w;
G[top].cost = cost;
G[top].next = head[u];
head[u] = top ++;
}
int inQ[MAXN + 64], dis[MAXN + 64], pre[MAXN + 64], path[MAXN + 64];
int SPFA(int s, int t)
{
memset(dis, 127, sizeof(dis));
dis[s] = 0;
queue<int>Q;
Q.push(s);
memset(inQ, 0, sizeof(inQ));
inQ[s] = 1;
memset(pre, - 1, sizeof(pre));
while(! Q.empty())
{
int u = Q.front();
Q.pop();
for(int i = head[u]; i != - 1; i = G[i].next)
{
int v = G[i].v;
if(G[i].w == 0 || dis[v] <= dis[u] + G[i].cost)
continue;
dis[v] = dis[u] + G[i].cost;
pre[v] = u;
path[v] = i;
if(! inQ[v])
Q.push(v), inQ[v] = 1;
}
inQ[u] = 0;
}
if(pre[t] == - 1)
return 0;
return 1;
}
int max_flow = 0;
int end(int s, int t)
{
int flow = INT_MAX, ret = 0;
for(int i = t; i != s; i = pre[i])
flow = min(flow, G[path[i]].w);
max_flow += flow;
for(int i = t; i != s; i = pre[i])
G[path[i]].w -= flow,
G[path[i] ^ 1].w += flow,
ret += flow * G[path[i]].cost;
return ret;
}
void print(int x)
{
int ans[10], top = 0;
if(x == 0)
putchar('0');
while(x)
ans[top ++] = x % 10, x /= 10;
for(; top; top --)
putchar(ans[top - 1] + '0');
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("L3381.in", "r", stdin);
freopen("L3381.out", "w", stdout);
#endif
int n, m, s, t;
read(n), read(m), read(s), read(t);
memset(head, - 1, sizeof(head));
top = 0;
for(int i = 0; i < m; i ++)
{
int u, v, w, cost;
read(u), read(v), read(w), read(cost);
addEdge(u, v, w, cost);
addEdge(v, u, 0, - cost);
}
int cost = 0;
while(SPFA(s, t))
cost += end(s, t);
print(max_flow), putchar(' '), print(cost);
}
二分图最大匹配: 洛谷P3386
https://www.luogu.org/problem/show?pid=3386
#include<cstdio>
#include<cctype>
#include<cstring>
#include<queue>
#include<climits>
#include<algorithm>
using namespace std;
void read(int &x)
{
char c;
int flag = 1;
x = 0;
while(! isgraph(c = getchar()))
if(c == '-')
flag *= - 1;
while(isgraph(c))
x = x * 10 + c - '0', c = getchar();
x *= flag;
}
const int MAXN = 1000, MAXM = 1000;
const int MAXE = MAXN * MAXM;
int head[MAXN + MAXM + 64];
int top;
struct edge
{
int v, w,next;
}G[(MAXE << 1) + (MAXN << 1) + (MAXM << 1) + 64];
void add_edge(int u, int v, int w)
{
G[top].v = v;
G[top].w = w;
G[top].next = head[u];
head[u] = top ++;
}
int dis[MAXN + MAXM + 64];
int BFS(int s, int t)
{
queue<int>Q;
Q.push(s);
memset(dis, - 1, sizeof(dis));
dis[s] = 0;
while(! Q.empty())
{
int u = Q.front();
Q.pop();
for(int i = head[u]; i != - 1; i = G[i].next)
if(G[i].w && dis[G[i].v] == - 1)
Q.push(G[i].v), dis[G[i].v] = dis[u] + 1;
}
return (dis[t] == - 1) ? 0 : 1;
}
int DFS(int u, int flow ,int t)
{
if(u == t)
return flow;
int max_flow = 0;
for(int i = head[u]; i != - 1; i = G[i].next)
{
int v = G[i].v;
if(G[i].w && dis[v] == dis[u] + 1)
{
int cur_flow = min(flow - max_flow, G[i].w);
cur_flow = DFS(v, cur_flow, t);
G[i].w -= cur_flow;
G[i ^ 1].w += cur_flow;
max_flow += cur_flow;
}
}
if(! max_flow)
dis[u] = - 1;
return max_flow;
}
void print(int x)
{
if(x < 0)
putchar('-'), x *= - 1;
if(x == 0)
putchar('0');
int ans[10], top = 0;
while(x)
ans[top ++] = x % 10, x /= 10;
for(; top; top --)
putchar(ans[top - 1] + '0');
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("L3386.in", "r", stdin);
freopen("L3386.out", "w", stdout);
#endif
int n, m, e;
read(n), read(m), read(e);
memset(head, - 1, sizeof(head));
top = 0;
for(int i = 0; i < e; i ++)
{
int u, v;
read(u), read(v);
add_edge(u, n + v, 1);
add_edge(n + v, u, 0);
}
for(int i = 1; i <= n; i ++)
add_edge(0, i, 1), add_edge(i, 0, 0);
for(int i = n + 1; i <= n + m; i ++)
add_edge(i, n + m + 1, 1), add_edge(n + m + 1, i, 0);
int flow = 0;
while(BFS(0, n + m + 1))
while(int del = DFS(0, INT_MAX, n + m + 1))
flow += del;
print(flow);
}
割点: 洛谷P3388
https://www.luogu.org/problem/show?pid=3388
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<deque>
using namespace std;
int n, m;
void read(int &x)
{
char c;
int flag = 1;
x = 0;
while(! isgraph(c = getchar()))
if(c == '-')
flag *= - 1;
while(isgraph(c))
x = x * 10 + c - '0', c = getchar();
x *= flag;
}
const int MAXN = (int)1e5;
const int MAXM = (int)1e5;
int top;
struct edge
{
int v, next;
}G[(MAXM << 1) + 64];
int head[MAXN + 64];
void add_edge(int u, int v)
{
G[top].v = v;
G[top].next = head[u];
head[u] = top ++;
}
int iscut[MAXN + 64];
int dfn[MAXN + 64], low[MAXN + 64];
deque<int>Q;
int vis[MAXN + 64];
int tarjan(int u, int fa)
{
vis[u] = 1;
Q.push_back(u);
low[u] = dfn[u] = dfn[fa] + 1;
int cnt = 0;
for(int i = head[u]; i != - 1; i = G[i].next)
{
int v = G[i].v;
if(v == fa)
continue;
if(dfn[v] == - 1)
{
cnt ++;
low[u] = min(tarjan(v, u), low[u]);
if(low[v] >= dfn[u])
iscut[u] = 1;
}
else
low[u] = min(dfn[v], low[u]);
}
if(low[u] == dfn[u])
{
if(Q.front() == u && cnt < 2) //注意: 对于根节点, 要特判
iscut[u] = 0;
while(Q.back() != u)
Q.pop_back();
Q.pop_back();
}
return low[u];
}
void print(int x)
{
if(x < 0)
putchar('-'), x *= - 1;
if(x == 0)
putchar('0');
int ans[10], top = 0;
while(x)
ans[top ++] = x % 10, x /= 10;
for(; top; top --)
putchar(ans[top - 1] + '0');
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("L3388.in", "r", stdin);
freopen("L3388.out", "w", stdout);
#endif
read(n), read(m);
top = 0;
memset(head, - 1, sizeof(head));
for(int i = 0; i < m; i ++)
{
int u, v;
read(u), read(v);
add_edge(u, v);
add_edge(v, u);
}
memset(iscut, 0, sizeof(iscut));
memset(dfn, - 1, sizeof(dfn));
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i ++)
if(! vis[i])
tarjan(i, i);
int cnt = 0;
for(int i = 1; i <= n ; i ++)
if(iscut[i])
cnt ++;
print(cnt);
putchar('
');
for(int i = 1; i <= n; i ++)
if(iscut[i])
print(i), putchar(' ');
}