HDU 5438(拓扑排序+并查集)
2015-09-28 21:12
309 查看
#include<iostream> #include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <queue> using namespace std; typedef long long ll; const int maxn=100010; int u[maxn],v[maxn]; int w[maxn],ind[maxn]; bool vis[maxn]; int p[maxn],ran[maxn]; //p数组为父亲,ran记录有联通块的里面的东西个数 ll sum[maxn]; //记录联通块的权值。 struct node { int to,next; } edge[maxn*20]; int head[maxn],num; void add(int u,int v) { edge[num].to=v; edge[num].next=head[u]; head[u]=num++; } int find(int x) { if(p[x]!=x) return p[x]=find(p[x]); return x; } void hebing(int a,int b) { int x=find(a); int y=find(b); if(x==y) return; p[y]=x; ran[x]+=ran[y]; sum[x]+=sum[y]; } void init(int n) { for(int i=1; i<=n; i++) { p[i]=i; ran[i]=1; sum[i]=w[i]; } } void to_sort(int n) { int i; queue<int>q; for(i=1; i<=n; i++) { if(ind[i]<=1) { q.push(i); vis[i]=0; } } while(!q.empty()) { int cur=q.front(); q.pop(); for(i=head[cur]; i!=-1; i=edge[i].next) { int xx=edge[i].to; if(vis[xx]) { ind[xx]--; if(ind[xx]==1) { q.push(xx); vis[xx]=0; } } } } } int main() { int t,i; scanf("%d",&t); while(t--) { int n,m; num=0; memset(vis,1,sizeof(vis)); memset(head,-1,sizeof(head)); memset(ind,0,sizeof(ind)); scanf("%d%d",&n,&m); for(i=1; i<=n; i++) scanf("%d",&w[i]); for(i=1; i<=m; i++) { scanf("%d%d",&u[i],&v[i]); add(u[i],v[i]); add(v[i],u[i]); ind[u[i]]++; ind[v[i]]++; } to_sort(n); init(n); for(i=1; i<=m; i++) { if(vis[u[i]] &&vis[v[i]]) hebing(u[i],v[i]); } ll ans=0; for(i=1; i<=n; i++) { if(p[i]==i &&vis[i] &&ran[i]%2==1) ans+=sum[i]; } cout<<ans<<endl; } return 0; }