hdu5438 拓扑+并查集 2015长春网赛

来源:互联网 发布:阿里云站点监控异常 编辑:程序博客网 时间:2024/04/27 13:33

刚学拓扑排序,记录图用链式向前星

用vis和queue删 度为1的点

然后并查集或dfs算结果。。

拓扑很容易死循环+查代码查了好久。。。

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <queue>#include <cmath>using namespace std;#define FOR(i, l, r) for(int i = l; i <= r; i++)#define REP(i, r, l) for(int i = r; i >= l; i--)typedef long long ll;double eps = 1e-6;const int maxn = 10010;const int mod = 1e9 + 7;int f[maxn];int u[maxn],v[maxn],w[maxn];int head[maxn];int ind[maxn];int vis[maxn];ll sum[maxn];int num[maxn];int tot;int n,m;struct edge{    int from, to, next;}edge[100010*2];void addedge( int from, int to){    tot++;    edge[tot].from = from;    edge[tot].to = to;    edge[tot].next = head[from];    head[from] = tot;}int find(int x){    if(f[x] != x)        return f[x] = find(f[x]);    return x;}void unionset(int x,int y){    int xx = find(x),yy = find(y);    if(xx != yy)    {        f[yy] = xx;        num[xx] += num[yy];        sum[xx] += sum[yy];    }}void topsort(){    queue <int> q;    FOR( i, 1, n)        if( ind[i] <= 1)            vis[i] = 1 , q.push(i);    while(!q.empty())    {        int temp=q.front();        q.pop();        for(int i = head[temp] ; i != -1 ; i = edge[i].next)        {            int x = edge[i].to;            if(vis[x]==0)            {                ind[x]--;                if( ind[x] == 1 )                {                    vis[x]=1;                    q.push(x);                }            }        }    }}int main(){    int T;    scanf( "%d", &T);    while(T--){        scanf( "%d%d", &n, &m);        FOR(i,1,n)        scanf( "%d", &w[i]);        tot=0;        memset( head, -1, sizeof(head));        memset( ind, 0, sizeof(ind));        memset( vis, false, sizeof(vis));        FOR( i, 1, m)        {            scanf( "%d%d" , &u[i], &v[i]);            addedge( u[i], v[i]);            addedge( v[i], u[i]);            ind[u[i]]++ , ind[v[i]]++;        }        topsort();        FOR( i, 1, n)            f[i]=i, num[i]=1, sum[i]=w[i];        FOR( i, 1, m)        {            if(vis[u[i]] == 0 && vis[v[i]] == 0)                unionset(u[i], v[i]);        }        ll ans=0;        FOR( i, 1, n)        if( f[i] == i && vis[i]==0 && num[i]%2)            ans += sum[i];        printf("%I64d\n", ans);    }    return 0;}


0 0