【連通圖|強連通分量+dfs】POJ-3160 Father Christmas flymouse

Father Christmas flymouse
Time Limit: 1000MS Memory Limit: 131072K

Description

After retirement as contestant from WHU ACM Team, flymouse volunteered to do the odds and ends such as cleaning out the computer lab for training as extension of his contribution to the team. When Christmas came, flymouse played Father Christmas to give gifts to the team members. The team members lived in distinct rooms in different buildings on the campus. To save vigor, flymouse decided to choose only one of those rooms as the place to start his journey and follow directed paths to visit one room after another and give out gifts en passant until he could reach no more unvisited rooms.

During the days on the team, flymouse left different impressions on his teammates at the time. Some of them, like LiZhiXu, with whom flymouse shared a lot of candies, would surely sing flymouse’s deeds of generosity, while the others, like snoopy, would never let flymouse off for his idleness. flymouse was able to use some kind of comfort index to quantitize whether better or worse he would feel after hearing the words from the gift recipients (positive for better and negative for worse). When arriving at a room, he chould choose to enter and give out a gift and hear the words from the recipient, or bypass the room in silence. He could arrive at a room more than once but never enter it a second time. He wanted to maximize the the sum of comfort indices accumulated along his journey.

Input

The input contains several test cases. Each test cases start with two integers N and M not exceeding 30 000 and 150 000 respectively on the first line, meaning that there were N team members living in N distinct rooms and M direct paths. On the next N lines there are N integers, one on each line, the i-th of which gives the comfort index of the words of the team member in the i-th room. Then follow M lines, each containing two integers i and j indicating a directed path from the i-th room to the j-th one. Process to end of file.

Output

For each test case, output one line with only the maximized sum of accumulated comfort indices.

Sample Input

2 2
14
21
0 1
1 0

Sample Output

35

Hint

32-bit signed integer type is capable of doing all arithmetic.

Source
POJ Monthly–2006.12.31, Sempr


題意: 給出一張有向圖,圖上各點有權值,權值可能爲負,選擇圖上一個頂點出發,每個點的權值可以選擇加或者不加1,求可能得到的最大權值和。

思路: 首先對於一個強連通分量,從任意一個點進入都可以到達分量中所有的點,因此先用Tarjan算法進行縮點。由於負權點根本不用加上權值,因此負權點權值設爲02

然後嘗試對每個入度爲0的點進行dfs,求出最大值。
代碼如下

/*
 * ID: j.sure.1
 * PROG:
 * LANG: C++
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <climits>
#include <iostream>
#define PB push_back
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
/****************************************/
const int N = 3e4 + 5, M = 15e4 + 5;
struct Edge {
    int v, next;
    Edge(){}
    Edge(int _v, int _next):
        v(_v), next(_next){}
}e[M];
int tot, deep, scc_cnt, n, m;
int head[N], dfn[N], scc_id[N], w[N];
int line[M][2], in[N], sum[N];
stack <int> s;
vector <int> ee[N];

void init()
{
    tot = deep = scc_cnt = 0;
    memset(head, -1, sizeof(head));
    memset(dfn, 0, sizeof(dfn));
    memset(scc_id, 0, sizeof(scc_id));
    memset(in, 0, sizeof(in));
    memset(sum, 0, sizeof(sum));
}

void add(int u, int v)
{
    e[tot] = Edge(v, head[u]);
    head[u] = tot++;
}

int dfs(int u)
{
    int lowu = dfn[u] = ++deep;
    s.push(u);
    for(int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].v;
        if(!dfn[v]) {
            int lowv = dfs(v);
            lowu = min(lowu, lowv);
        }
        else if(!scc_id[v]) {
            lowu = min(lowu, dfn[v]);
        }
    }
    if(lowu == dfn[u]) {
        scc_cnt++;
        while(1) {
            int x = s.top(); s.pop();
            scc_id[x] = scc_cnt;
            sum[scc_cnt] += w[x];
            if(x == u) break;
        }
    }
    return lowu;
}

void tarjan()
{
    for(int i = 0; i < n; i++) {
        if(!dfn[i]) dfs(i);
    }
}

int dfs2(int u, int tmp)
{
    int sz = ee[u].size();
    int maxi = tmp;
    for(int i = 0; i < sz; i++) {
        int v = ee[u][i];
        maxi = max(maxi, dfs2(v, tmp + sum[v]));
    }
    return maxi;
}

int solve()
{
    int ans = 0;
    for(int i = 1; i <= scc_cnt; i++) ee[i].clear();
    for(int i = 0; i < m; i++) {
        int u = scc_id[line[i][0]], v = scc_id[line[i][1]];
        if(u != v) {
            in[v]++;
            ee[u].PB(v);
        }
    }
    for(int i = 1; i <= scc_cnt; i++) {
        if(!in[i]) {
            ans = max(ans, dfs2(i, sum[i]));
        }
    }
    return ans;
}

int main()
{
#ifdef J_Sure
    freopen("000.in", "r", stdin);
    //freopen("999.out", "w", stdout);
#endif
    while(~scanf("%d%d", &n, &m)) {
        init();
        for(int i = 0; i < n; i++) {
            scanf("%d", &w[i]);
            if(w[i] < 0) w[i] = 0;
        }
        int u, v;
        for(int i = 0; i < m; i++) {
            scanf("%d%d", &u, &v);
            add(u, v);
            line[i][0] = u; line[i][1] = v;
        }
        tarjan();
        int ans = solve();
        printf("%d\n", ans);
    }
    return 0;
}

  1. 題意描述不清楚,假如整張圖都是負權,答案是0。
  2. 不得不懷疑出題人是否腦殘。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章