HDU5438 深搜 + 广搜 xingxing在努力

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;
typedef long long LL;

int p, m;
int pw[10000 + 100];
vector<int> G[10000 + 10];
int exist[10000 + 10];
int degree[10000 + 10];

void topo()
{
    queue<int> que;
    for(int i=1; i<=p; i++)
        if(degree[i]<=1) que.push(i);
    while(!que.empty())
    {
        int u = que.front(); que.pop();
        exist[u] = 0;
        for(int i=0; i<G[u].size(); i++)
        {
            int v = G[u][i];
            degree[v]--;
            if(degree[v] <= 1&&exist[v])
                que.push(v);
        }
    }
}

int vis[10000 + 10];
LL dfs(int u, int &num)    //有num个结点   返回值是连通图的点权和
{
    vis[u] = 1;
    num++;
    LL res = pw[u];
    for(int i=0; i<G[u].size(); i++)
    {
        int v = G[u][i];
        if(!vis[v] && exist[v])
            res += dfs(v, num);
    }
    return res;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &p, &m);
        for(int i=1; i<=p; i++)
        {
            scanf("%d", &pw[i]);
            G[i].clear();
            exist[i] = 1;
            degree[i] = 0;
            vis[i] = 0;
        }
        for(int i=1; i<=m; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
            degree[u]++;
            degree[v]++;
        }
        topo();
        LL res = 0;
        for(int i=1; i<=p; i++) if(!vis[i]&&exist[i])     //调用dfs的条件和dfs递归的条件一样
        {
            int num = 0;
            LL tp = dfs(i, num);
            if((num&1) == 1)
            {
                res += tp;
            }
        }
        printf("%lld\n", res);
    }
    return 0;
}

 

之所以把这个题归为图论是因为这道题用了类似拓扑排序的思想除去多余的边, 然后再dfs求连通块。。 代码如下:

posted @ 2015-11-16 16:34  xing-xing  阅读(104)  评论(0)    收藏  举报