HDU 5438 topo

HDU 5438

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5438

题意:

一些点一些边。每次去除只有一条边和该点相邻的点,并把该点的边全删除。

问最后点数为奇数个的连通块里面点的权值和。

思路:

Topo,然后任意姿势求奇数个点的集合。

并查集比较好实现,dfs亦可。你非要双连通缩点我也没有办法。

源码:

#include <iostream>

#include <iomanip>

#include <sstream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cctype>

#include <ctime>

#include <climits>

#include <cassert>

#include <cmath>

#include <string>

#include <bitset>

#include <vector>

#include <deque>

#include <list>

#include <set>

#include <map>

#include <queue>

#include <stack>

#include <algorithm>

#include <functional>

#include <utility>

#include <numeric>

#define LL long long

#define gmax(a,b) ((a) > (b) ? (a) : (b))

#define gmin(a,b) ((a) < (b) ? (a) : (b))

#define MOD (1000000007)

using namespace std;

/*注意是边不是点*/

const int MAXN = 1e4 + 5;

vector<int>lin[MAXN];

int n, m;

long long data[MAXN];

int in[MAXN];

queue<int>que;

int use[MAXN];

long long tans;

int dfs(int u)

{

    int ans = 1;

    use[u] = 1;

    tans += data[u];

    for(int i = 0 ; i < (int)lin[u].size() ; i++){

        int v = lin[u][i];

        if(use[v] == 0) ans += dfs(v);

    }

    return ans;

}

int main()

{

//    freopen("1002.in", "r", stdin);

    int t;

    scanf("%d", &t);

    while(t--){

        scanf("%d%d", &n, &m);

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

            in[i] = 0, lin[i].clear(), scanf("%I64d", &data[i]);

        int u, v;

        for(int i = 1 ; i <= m ; i++){

            scanf("%d%d", &u, &v);

            lin[u].push_back(v);

            lin[v].push_back(u);

            in[u]++;

            in[v]++;

        }

        memset(use, 0, sizeof(use));

        while(!que.empty()) que.pop();

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

            if(in[i] <= 1)  que.push(i), use[i] = 1;

        while(!que.empty()){

            int u = que.front();    que.pop();

            for(int i = 0 ; i < (int)lin[u].size() ; i++){

                int v = lin[u][i];

                in[v]--;

                if(use[v] == 0 && in[v] <= 1)   que.push(v), use[v] = 1;

            }

        }

        long long ans = 0;

        for(int i = 1 ; i <= n ; i++){

            if(use[i] == 0){

                tans = 0;

                int num = dfs(i);

                if(num % 2 == 1)

                    ans += tans;

            }

        }

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

    }

    return 0;

}

 

你可能感兴趣的:(HDU 5438 topo)