颓废again

[POI2938]病毒

AC自动机好题,正解挺套路的。在AC自动机上建立Trie图。如果不是危险节点的字母能连成一条环。那么就有无限长的安全代码。

AC代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
const int MAXN = 100000;
const int CHA = 2;
using namespace std;

inline int read() {
    int x = 0, w = 1; char c = ' ';
    
    while (c < '0' || c > '9') {
        c = getchar(); if (c == '-') w = -1;
    }
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    
    return x * w;
}

char P[MAXN + 5];
bool f = true;

class AcAutomaton {
    public :
        AcAutomaton() {}
        void insert(char *P);
        void GetFail();
        void dfs(int u);
    private :
        queue < int > Q;
        int tot, fail[MAXN + 5], Trie[MAXN + 5][CHA];
        bool val[MAXN + 5], vis[MAXN + 5], InSta[MAXN + 5];
}AC;

void AcAutomaton::insert(char *P) {
    int now = 0, L = strlen(P); 
    
    for (int i = 0; i < L; ++i) {
        int c = P[i] - '0';
        
        if (!Trie[now][c]) Trie[now][c] = ++tot;
        now = Trie[now][c];
    }
    
    val[now] = true;
}

void AcAutomaton::GetFail() { 
    for (int i = 0; i < CHA; ++i) {
        int u = Trie[0][i];
        
        if (u) fail[u] = 0, Q.push(u);
    }
    
    while (!Q.empty()) {
        int cur = Q.front(); Q.pop();
        
        for (int i = 0; i < CHA; ++i) {
            int u = Trie[cur][i];
            
            if (u)
                fail[u] = Trie[fail[cur]][i], val[u] |= val[fail[u]], Q.push(u);
            else
                Trie[cur][i] = Trie[fail[cur]][i];
        }
    }
}

void AcAutomaton::dfs(int u) {
    if (!f) return;

    InSta[u] = true, vis[u] = true;
    
    for (int i = 0; i < CHA; ++i) {
        int v = Trie[u][i];

        if (InSta[v]) {
            f = false; return;
        }
        else if (!vis[v] && !val[v])
            dfs(v);    
    }
    
    InSta[u] = false;
}

int main() {
    int n = read();
    for (int i = 1; i <= n; ++i) 
        scanf("%s", P), AC.insert(P);

    AC.GetFail();
    AC.dfs(0);
    if (f) puts("NIE"); else puts("TAK");
    
    return 0;
}

最大流

省选时候考了最大流。大家都说是套路题,然而我看不出来。

所以我又重新学习了一遍最大流的Dinic算法(原来只会递归版Isap)。

加了一些玄学优化,在LOJ上跑得比Isap快几十倍,不知道怎么回事。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define min(a, b) (a < b ? a : b)
typedef long long LL;
const int MAXN = 100000;
const int INF = 0x3f3f3f3f;
using namespace std;

inline int read() {
    int x = 0, w = 1; char c = ' ';
    
    while (c < '0' || c > '9') {
        c = getchar(); if (c == '-') w = -1;
    }
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();

    return x * w;
}

struct Node {
    int to, w, nxt;
};

class Graph {
    public:
        Graph() {tot = 0, memset(head, -1, sizeof(head));}
        void add(int u, int v, int w) {
            edge[tot] = (Node) {v, w, head[u]}, head[u] = tot++;
            edge[tot] = (Node) {u, 0, head[v]}, head[v] = tot++;
        }
        bool bfs(int s, int t); int dfs(int u, int t, int flow);
        LL Dinic(int s, int t);
    private:
        Node edge[MAXN * 2 + 5];
        int tot, level[MAXN + 5], head[MAXN + 5], cur[MAXN + 5];
        queue < int > Q;
}G;

bool Graph::bfs(int s, int t) {
    memset(level, 0, sizeof(level));
    while (!Q.empty()) Q.pop();
    
    Q.push(s), level[s] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();

        for (int i = head[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].to, cap = edge[i].w;

            if (cap && !level[v]) {
                Q.push(v); 
                level[v] = level[u] + 1;
                if (v == t) return true;           
            }
        }
    }
    
    return level[t];
}

int Graph::dfs(int u, int t, int flow) {
    if (u == t || !flow) return flow;
    int used = 0;

    for (int &i = cur[u]; ~i && used < flow; i = edge[i].nxt) {
        int v = edge[i].to, &cap = edge[i].w, &rcap = edge[i ^ 1].w;

        if (cap && level[u] + 1 == level[v]) {
            int d = dfs(v, t, min(cap, flow - used));

            if (d) {
                cap -= d, rcap += d;
                used += d;

                return d;
            }
            else 
                level[v] = -INF;
        }
    }
    
    return 0;
}

LL Graph::Dinic(int s, int t) {
    LL MaxFlow = 0;
    
    while (bfs(s, t)) {
        memcpy(cur, head, sizeof(head));
        while (int f = dfs(s, t, INF)) MaxFlow += f;
    }

    return MaxFlow;
}

int main() {
    int n = read(), m = read(), s = read(), t = read();

    for (int i = 1; i <= m; ++i) {
        int u = read(), v = read(), w = read();
        G.add(u, v, w);
    }

    printf("%d\n", G.Dinic(s, t));

    return 0;
}
posted @ 2018-04-15 20:52  23forever  阅读(166)  评论(0编辑  收藏  举报