您的位置:首页 > 理论基础 > 计算机网络

HDU 5438 Ponds (2015年长春赛区网络赛B题)

2015-09-14 14:05 549 查看
1.题目描述:点击打开链接

2.解题思路:本题利用拓扑排序+并查集解决。由于以前没用过用队列来模拟一个拓扑排序过程,比赛时候这道题做的异常艰难才通过==。如果用队列来处理的话,就会方便很多,首先入队列的是degree小于2的点,然后从这些点出发,和他相邻的点的degree都要减小1,如果发现相邻结点的degree也小于2了,那么加入队列,同时标记所有degre小于2的点,表示他们已经被删除了。这样,剩下的没有被标记的点一定是构成了一个环,然后用并查集来更新连通块的个数,权值,最后求和即可。

3.代码:

#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define me(s)  memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;

const int N=10000+5;
struct Edge
{
    int u,v;
}e[100000+10];
vector<int>g
;
int p
,c
;
ll w
;
int deg
,vis
;
int n,m;

void init()
{
    me(g);me(vis);me(deg);
    for(int i=0;i<n;i++)
        p[i]=i,c[i]=1;
}
int find(int x){return p[x]==x?x:p[x]=find(p[x]);}
void addedge(int id,int u,int v)
{
    g[u].push_back(v);
    g[v].push_back(u);
    deg[u]++,deg[v]++;
    e[id].u=u,e[id].v=v;
}

void toposort()//利用一个队列来模拟一个拓扑排序
{
    queue<int>q;
    me(vis);
    for(int i=0;i<n;i++)
        if(deg[i]<2)
        {
            q.push(i);
            vis[i]=1;
        }
    while(!q.empty())
    {
        int u=q.front();q.pop();
        int len=g[u].size();
        for(int i=0;i<len;i++)
        {
            int v=g[u][i];
            if(vis[v])continue;
            deg[v]--;
            if(deg[v]<2)
            {
                vis[v]=1;
                q.push(v);
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<n;i++)
            scanf("%I64d",&w[i]);
        int u,v;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            u--,v--;
            addedge(i,u,v);
        }
        toposort();
        for(int i=0;i<m;i++)
        {
            int u=e[i].u,v=e[i].v;
            if(vis[u]||vis[v])continue;
            int x=find(u),y=find(v);
            if(x!=y)
            {
                c[y]+=c[x];
                w[y]+=w[x];
                p[x]=y;
            }
        }
        ll ans=0;
        for(int i=0;i<n;i++)
            if(!vis[i]&&p[i]==i&&(c[i]&1))
                    ans+=w[i];
        printf("%I64d\n",ans);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: