hdu 5438(拓扑+bfs)

时间:2023-03-09 15:10:51
hdu 5438(拓扑+bfs)

题意:建图,删掉所有连接点小于2的点,直到不能删为止,问最后剩余的联通块中,点的数量是奇数的联通块中的点的权值和。

思路:拓扑删点,bfs计算

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
vector<int>q[10005];
int p[10005];
int vis[10005];
int in[10005];
int Q[10005];
ll ans,num;
queue<int>que; void bfs()
{
while(!que.empty())
{
int u = que.front();
que.pop();
if(vis[u])
continue;
vis[u] = 1; num++;
ans+= p[u];
for(int i = 0; i < q[u].size(); i++)
{
int x = q[u][i];
if(in[x] < 2)
continue;
que.push(x);
}
}
return;
}
int n;
void topsort()
{
int head_=1,tail=0;
for(int i=1; i<=n; i++)
if(in[i] < 2 && in[i] > 0)
{
Q[++tail]=i;
in[i] -= 2;
}
while (head_<=tail)
{
int now=Q[head_];
for(int j=0; j < q[now].size(); j++)
{
int v = q[now][j];
in[v]--;
if (in[v] < 2 && in[v]>0)
{
in[v]-=2;
Q[++tail]=v;
}
}
head_++;
}
} int main()
{
int T,m,a,b;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
scanf("%d",&p[i]);
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
for(int i = 1; i <= m; i++)
{
scanf("%d%d",&a,&b);
q[a].push_back(b);
q[b].push_back(a);
in[a]++;
in[b]++;
}
topsort();
while(!que.empty())
que.pop();
ll all=0;
for(int i = 1; i <= n; i++)
{
if(!vis[i] && in[i] >= 2)
{
ans = 0;
num = 0;
que.push(i);
bfs();
if(num %2 == 1)
{
all += ans;
}
}
}
if(n==1)
printf("0\n");
else
printf("%I64d\n",all);
for(int i = 1; i <= n; i++)
{
q[i].clear();
}
} return 0;
}