您的位置:首页 > 其它

HDU5438 拓扑排序

2015-09-18 21:38 295 查看
题目here

有n个水池,每个水池有价值v,有m条水管连接 a b 两个水池 ,现在要求把只有两个以下相邻水池的水池去掉,直到不能去为止,最后将各组水池中,集合数为奇数的组的水池价值总和加起来。

拓扑排序练习题

#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
vector<int>v[10010];
int m,n;
int val[10010];
queue<int>q;
int vis[10010];
int ru[10010];
int cnt;
long long sum,ans;
void dfs(int k)
{
vis[k]=1;
cnt++;
sum+=val[k];
for(int i=0;i<v[k].size();i++)
{
int t=v[k][i];
if(!vis[t])
{
dfs(t);
}
}
}
void topsort()
{
memset(vis,0,sizeof(vis));
while(!q.empty())q.pop();
for(int i=1;i<=n;i++)
{
if(ru[i]<2)
{
q.push(i);
vis[i]=1;
}
}
while(!q.empty())
{
int root=q.front();q.pop();
// printf("%d\n",root);
for(int i=0;i<v[root].size();i++)
{
int t=v[root][i];
if(vis[t])continue;
ru[t]--;
if(!vis[t]&&ru[t]<2)
{
q.push(t);
vis[t]=1;
}
}
}
ans=0;
for(int i=1;i<=n;i++)
{
if(vis[i])continue;
sum=0;cnt=0;
dfs(i);
if(cnt%2==1)ans+=sum;
}
printf("%lld\n",ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)v[i].clear();
memset(ru,0,sizeof(ru));
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
ru[a]++;
ru[b]++;
}
topsort();

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: