POJ 3160 Father Christmas flymouse 解题报告

一个经典的图DP,首先对无向图进行强联通分量缩点变成DAG,这样就可以在DAG上用拓扑序做DP

需要注意的是点权是有负数的情况为此WA无数次

附代码供后人参考

#include <cstdio>

#include <algorithm>

#include <cstring>

#define DEBUG(x) cout << #x << " " << x << endl;

using namespace std;



class scc

{

private:

        const static int V = 50001;

        const static int E = 150000;



        struct edge

        {

                int v;

                edge *nxt;

        } pool[E * 3], *g[V], *pp, *gscc[V];

        int n, m, st[V], top;

        int val[V], valscc[V], dp[V];

        int tms[V], pt;

        bool reach[V];

        int dfn[V], low[V], idx[V];

        int cnt, depth;

        void dfs(int x);

        void build_newgraph();



        void addnewedge(int u, int v)

        {

                pp->v = v;

                pp->nxt = gscc[u];

                gscc[u] = pp++;

        }

        void toposort(int x);

public:



        void addedge(int u, int v)

        {

                pp->v = v;

                pp->nxt = g[u];

                g[u] = pp++;

        }

        void initialize(int n);

        void solve();

} g;



void scc::initialize(int n)

{

        this->n = n;

        memset(g, 0, sizeof (g));

        memset(reach, false, sizeof (reach));

        memset(dfn, 0, sizeof (dfn));

        for (int i = 0; i < n; i++)

                scanf("%d", &val[i]);

        pp = pool;

        depth = pt = top = cnt = 0;

}



void scc::dfs(int x)

{

        st[++top] = x;

        int w;

        dfn[x] = low[x] = ++depth;

        for (edge *i = g[x]; i != NULL; i = i->nxt)

        {

                w = i->v;

                if (reach[w])

                        continue;

                else if (dfn[w] == 0)

                {

                        dfs(w);

                        if (low[w] < low[x])

                                low[x] = low[w];

                }

                else if (dfn[w] < low[x])

                        low[x] = dfn[w];

        }

        if (low[x] == dfn[x])

        {

                cnt++;

                do

                {

                        w = st[top--];

                        idx[w] = cnt;

                        reach[w] = true;

                }

                while (w != x);

        }

}



void scc::solve()

{

        for (int i = 0; i < n; i++)

                if (!reach[i])

                        dfs(i);

        build_newgraph();

        memset(reach, false, sizeof (reach));

        for (int i = 1; i <= cnt; i++)

                if (!reach[i])

                        toposort(i);

        memset(dp, 0, sizeof (dp));

        for (int i = 0; i < pt; i++)

        {

                int w = tms[i], tmp = 0;

                dp[w] = valscc[w];

                for (edge *j = gscc[w]; j != NULL; j = j->nxt)

                        tmp = max(tmp, dp[j->v]);

                dp[w] += tmp;

        }

        int ans = dp[1];

        for (int i = 2; i <= cnt; i++)

                ans = max(ans, dp[i]);

        printf("%d\n", ans);

}



void scc::toposort(int x)

{

        reach[x] = true;

        for (edge *i = gscc[x]; i != NULL; i = i->nxt)

                if (!reach[i->v])

                        toposort(i->v);

        tms[pt++] = x;

}



void scc::build_newgraph()

{

        memset(gscc, 0, sizeof (gscc));

        memset(valscc, 0, sizeof (valscc));

        for (int i = 0; i < n; i++)

                if(val[i] > 0)

                        valscc[idx[i]] += val[i];

        for (int i = 0; i < n; i++)

                for (edge *j = g[i]; j != NULL; j = j->nxt)

                        if (idx[i] != idx[j->v])

                                addnewedge(idx[i], idx[j->v]);

}



int main()

{

        scc g;

        int n, m, vfrom, vto;

        while (scanf("%d %d", &n, &m) == 2)

        {

                g.initialize(n);

                for (int i = 0; i < m; i++)

                {

                        scanf("%d %d", &vfrom, &vto);

                        g.addedge(vfrom, vto);

                }

                g.solve();

        }

        return 0;

}



你可能感兴趣的:(poj)