hdu 5438 Ponds

/*
  删除所有度小于2的节点,求剩余联通快大小
  把要删除的点压入队列,删除与他的所有连边,如果删除该边后,与该点相连的点度小于2,那么把那个点压人队列
  最后并查集/dfs/bfs之类的判断联通块大小就好了
*/

#include<bits/stdc++.h> using namespace std; const int maxn=1e4+5; typedef long long ll; vector<int> g[maxn];//边 int deg[maxn],f[maxn],v1[maxn],n,m; ll v2[maxn]; bool vis[maxn],va[maxn]; void init(){ for(int i=0;i<=n;i++){ g[i].clear(); f[i]=i;v1[i]=1; deg[i]=0; } memset(vis,true,sizeof(vis)); memset(va,true,sizeof(va)); } void input(){ for(int i=1;i<=n;i++) scanf("%lld",&v2[i]); while(m--){ int u,v; scanf("%d%d",&u,&v); deg[u]++;deg[v]++; g[u].push_back(v); g[v].push_back(u); } } int find(int x){ return f[x]==x?x:f[x]=find(f[x]); } void uion(int a,int b){ int t1=find(a); int t2=find(b); if(t1!=t2){ f[t1]=t2; v1[t2]+=v1[t1]; v2[t2]+=v2[t1]; } } void solve(){ queue<int> q; for(int i=1;i<=n;i++) if(deg[i]<2) q.push(i),vis[i]=0; //删除度小于2节点 while(!q.empty()){ int u=q.front();q.pop(); for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(vis[v]){ deg[v]--; if(deg[v]<2) q.push(v),vis[v]=0; } } } //求奇数联通块价值的和 for(int i=1;i<=n;i++){ if(!vis[i])continue; for(int j=0;j<g[i].size();j++){ int u=g[i][j]; if(!vis[u])continue; //cout<<i<<" "<<u<<endl; uion(i,u); } } ll ans=0; for(int i=1;i<=n;i++){ if(!vis[i])continue; int t1=find(i); //cout<<v1[t1]<<endl; if(!va[t1]||v1[t1]%2==0)continue; ans+=v2[t1]; va[t1]=0; } cout<<ans<<endl; } int main(){ int t;scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); init(); input(); solve(); } return 0; }

  

posted @ 2017-04-24 15:59  N维解析几何  阅读(128)  评论(0编辑  收藏  举报