因为删除一个点后会影响其相邻节点的度数,所以可以用bfs将删除某一点之后,度数变为<=1的邻居节点push到队列中。注意同一个节点可能被不同的邻居访问多次,所以这里面不能用vis[x]标记重复访问,但是被删除的点要避免访问。
计算连通分量用bfs即可,另外最后的答案可能会爆int。
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include <ctype.h>
#include<map>
#include<time.h>
using namespace std;
//hdu 5438
const int maxn=10010;
int T;
int p;
int m;
vector<int>mp[maxn];
long long v[maxn];
int deg[maxn];
bool del[maxn];
bool vis[maxn];
long long ans;
void bfs(int st)
{
queue<int>que;
que.push(st);
while(!que.empty())
{
int now=que.front();
que.pop();
del[now]=true;
vis[now]=true;
deg[now]--;
for(int i=0;i<mp[now].size();i++)
{
int nei=mp[now][i];
if(del[nei]==true) continue;
//if(vis[nei]==true) continue;
deg[nei]--;
if(deg[nei]<=1)
{
que.push(nei);
}
}
}
}
void bfs_connect(int st)
{
queue<int>que;
que.push(st);
long long sum=0;
int cnt=0;
while(!que.empty())
{
int now=que.front();
que.pop();
cnt++;
sum+=v[now];
vis[now]=true;
for(int i=0;i<mp[now].size();i++)
{
int nei=mp[now][i];
if(del[nei]==true) continue;
if(vis[nei]==true) continue;
que.push(nei);
vis[nei]=true;
}
}
if(cnt%2==1)
{
ans+=sum;
}
}
int main()
{
freopen("input.txt","r",stdin);
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
memset(v,0,sizeof(v));
memset(mp,0,sizeof(mp));
memset(deg,0,sizeof(deg));
memset(del,false,sizeof(del));
memset(vis,false,sizeof(vis));
ans=0;
scanf("%d %d",&p,&m);
for(int i=1;i<=p;i++)
{
scanf("%I64d",&v[i]);
}
int a=0;
int b=0;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
mp[a].push_back(b);
mp[b].push_back(a);
deg[a]++;
deg[b]++;
}
for(int i=1;i<=p;i++)
{
if(deg[i]==0)
{
del[i]=true;
}
else if(deg[i]==1&&del[i]==false)
{
bfs(i);
}
}
memset(vis,false,sizeof(vis));
for(int i=0;i<=p;i++)
{
if(vis[i]==false&&del[i]==false)
{
bfs_connect(i);
}
}
printf("%I64d\n",ans);
}
return 0;
}