题意:
有n个池塘、m个管道,每个池塘有权值,m个管道用来连接池塘(无向边),我们要把度小于2的池塘删除,统计每个包含池塘数是奇数的连通分量的权值并输出。
思路:
拓扑排序之后,删点,然后dfs一遍就好了。因为用int没用long long WA了一次。
代码;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const long long maxn = 10005;
long long du[maxn];
long long val[maxn];
queue<int> q;
struct E {
long long to, next;
}e[100005];
long long tot;
long long head[maxn];
void init() {
memset(head, 0, sizeof(head));
tot =1;
}
void add(long long u, long long v) {
e[tot].to = v;
e[tot].next = head[u];
head[u] = tot++;
}
long long vis[maxn];
long long ans = 0;
long long cnt = 0;
void dfs(long long u, long long &num, long long &sum) {
for(long long i = head[u]; i; i = e[i].next) {
long long v = e[i].to;
if(!vis[v]) {
vis[v] = 1;
num++;
sum += val[v];
dfs(v, num, sum);
}
}
}
int main() {
long long t;
long long n, m;
scanf("%I64d",&t);
while(t--) {
init();
scanf("%I64d %I64d",&n, &m);
for(long long i = 1; i <= n; i++) {
scanf("%I64d",&val[i]);
}
memset(du, 0, sizeof(du));
for(long long i = 1; i <= m; i++) {
long long u, v;
scanf("%I64d %I64d",&u, &v);
du[u]++; du[v]++;
add(u, v);
add(v, u);
}
while(!q.empty()) q.pop();
memset(vis, 0, sizeof(vis));
for(long long i = 1; i <= n; i++) {
if(du[i] <= 1){
vis[i] = 1;
q.push(i);
}
}
while(!q.empty()) {
long long u = q.front(); q.pop();
for(long long i = head[u]; i; i = e[i].next) {
long long v = e[i].to;
if(!vis[v]) {
du[v] --;
if(du[v] <= 1) {
vis[v] = 1;
q.push(v);
}
}
}
}
ans = 0;
for(long long i = 1; i <= n; i++) {
if(!vis[i]) {
vis[i] = 1;
long long num = 1, sum = val[i];
dfs(i, num, sum);
if(num % 2 == 1) {
ans += sum;
}
}
}
printf("%I64d\n", ans);
}
}