Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 5797 Accepted Submission(s): 1605 Problem Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, and there will not be more than one pipe between two ponds. Each pond has a value v .
Input The first line of input will contain a number T(1≤T≤30) which is the number of test cases.
Output For each test case, output the sum of the value of all connected components consisting of odd number of ponds after removing all the ponds connected with less than two pipes.
Sample Input 1 7 7 1 2 3 4 5 6 7 1 4 1 5 4 5 2 3 2 6 3 6 2 7
Sample Output 21
Source 2015 ACM/ICPC Asia Regional Changchun Online
Recommend hujie
|
题目大意:给你N个点M条边,现在给你N个点的权值和M条路(无向),现在要你删除这个图中的度数为0或1的节点,最后统计图中节点数目为奇数的联通块的值(值的统计方式是每个点的权值相加)
思路:这个题目的话,很容易就想到了拓扑排序,差不错的删除点的方式,最后的统计当时比赛的时候没想出来,后来看了网上的题解思路想到并差集把图收缩到一个个的节点上去最后统计,学到了
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1e4+5;
int n,m,L[maxn],R[maxn],C[maxn];
ll W[maxn];
int vis[maxn],degree[maxn];
int F[maxn];
vector<int >G[maxn];
int findset(int x)
{
if(F[x]==-1)
return x;
return F[x]=findset(F[x]);
}
void init()
{
scanf("%d%d",&n,&m);
memset(vis,0,sizeof(vis));
memset(degree,0,sizeof(degree));
memset(F,-1,sizeof(F));
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1;i<=n;i++)
scanf("%lld",&W[i]);
int u,v;
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
degree[u]++,degree[v]++;
G[u].push_back(v);
G[v].push_back(u);
L[i]=u,R[i]=v;
}
}
ll solve()
{
queue<int >Q;
for(int i=1;i<=n;i++)
{
if(degree[i]<2)
{
Q.push(i);
vis[i]=1;
}
}
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(vis[v]) continue;
degree[v]--;
if(degree[v]<2)
{
Q.push(v);
vis[v]=1;
}
}
}
for(int i=0;i<=n;i++)
{
C[i]=1;
}
for(int i=0;i<m;i++)
{
int u=L[i],v=R[i];
if(vis[u]||vis[v]) continue;
if(findset(u)!=findset(v))
{
C[findset(v)]+=C[findset(u)];
W[findset(v)]+=W[findset(u)];
F[findset(u)]=findset(v);
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
if(vis[i]||findset(i)!=i) continue;
if(C[i]&1)
ans+=W[i];
}
return ans;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
init();
cout<<solve()<<endl;
}
return 0;
}