最近水的一些模板题

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('\n'), 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('\n');
    for(int i = 1; i <= n; i ++)
        if(iscut[i])
            print(i), putchar(' ');
}
posted @ 2016-12-18 21:32  Zeonfai  阅读(139)  评论(0编辑  收藏  举报