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; }