标签:
先dfs对度小于2的删边,知道不能删为止。
然后通过并查集来计算每一个分量里面几个元素。
#include<iostream> #include<cstring> #include<vector> #define maxn 10010 #define LL __int64 using namespace std; int in[maxn],vis[maxn],p,pa[maxn],cou[maxn]; LL sum[maxn]; vector<int>mp[maxn]; void dfs(int u) { int i; vis[u]=1; for(i=0;i<mp[u].size();i++) { in[u]--; in[mp[u][i]]--; if(!vis[mp[u][i]]&&in[mp[u][i]]<2) dfs(mp[u][i]); } } int Find(int x) { if(x!=pa[x]) pa[x]=Find(pa[x]); return pa[x]; } int main() { int i,j,t,q; cin>>t; while(t--) { cin>>p>>q; for(i=0;i<=p;i++) { mp[i].clear(); pa[i]=i; cou[i]=1; vis[i]=0; in[i]=0; } for(i=1;i<=p;i++) { cin>>sum[i]; } while(q--) { int x,y; cin>>x>>y; mp[x].push_back(y); mp[y].push_back(x); in[x]++; in[y]++; } int flag; while(1) { flag=0; for(i=1;i<=p;i++) { if(!vis[i]&&in[i]<2) { flag=1; break; } } if(flag==0) break; for(i=1;i<=p;i++) { if(!vis[i]&&in[i]<2) { dfs(i); } } } /*for(i=1;i<=p;i++) { printf("%d ",in[i]); } printf("\n"); for(i=0;i<mp[1].size();i++) { printf("%d ",mp[1][i]); } printf("\n");*/ for(i=1;i<=p;i++) { if(vis[i])continue; int fx=Find(i); int num=mp[i].size(); //printf("%d ",fx); for(j=0;j<num;j++) { if(!vis[mp[i][j]]&&in[mp[i][j]]>=2) { int fy=Find(mp[i][j]); if(fx==fy)continue; //printf("%d ",mp[i][j]); pa[fy]=fx; sum[fx]+=sum[fy]; cou[fx]+=cou[fy]; //printf("%d ",cou[fx]); } } //printf("\n"); } LL ans=0; for(i=1;i<=p;i++) { if(pa[i]==i&&!vis[i]&&cou[i]%2&&cou[i]!=1) { //printf("%I64d ",sum[i]); ans+=sum[i]; } } //puts(""); printf("%I64d\n",ans); } } /* 9 9 1 2 3 4 5 6 7 8 9 1 2 2 3 3 4 1 4 2 5 5 6 7 8 8 9 7 9 */
标签:
原文地址:http://www.cnblogs.com/sweat123/p/4808802.html