您的位置:首页 > 其它

hdu 5438 搜索

2015-09-17 16:19 183 查看
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.

Now Betty wants to remove some ponds because she does not have enough money. But each time when she removes a pond, she can only remove the ponds which are connected with less than two ponds, or the pond will explode.

Note that Betty should keep removing ponds until no more ponds can be removed. After that, please help her calculate the sum of the value for each connected component consisting of a odd number of ponds

这个题目比赛的时候想到的是吧所有的东西连在一起,就使用并查集来连,但是以想到还要删除掉之后,就觉得没用了。然后,一个队友想到用向量来记录链接的情况,蓝后按照条件来一个个删除。但是好像向量里面删数的效率不高,光荣的tle了;

赛后看来题解,发现这个题目用一下邻接表和深搜救可以搞定了;

首先对根据提议,建立一个双向连接的邻接表,记录每条边的时候顺便记录下每个池塘链接的池塘个数。然后开个队列,对满足了连接的池塘的数目小于2的进行处理。(注意有的池塘连接的其他池塘数目可能为0 ,开始的时候因为这个wrong了)。  然后对每个满足条件的池塘放进队列。 取出队列的池塘编号,把和这个池塘连接的池塘的连接数都减去1。如果还有满足的继续放入队列;

按照上面的那样处理之后, 所有能删除的就都删除了。

在上面处理的时候,要都每个处理过的,都要标记过;

之后对每个还没标记过的进行深搜,对搜过的点标记,记录下每个联通块中池塘的个数,满足大于2(应该也是可以不加的,不过并没有测试过) 并且是奇数的加上答案;

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
struct Edge{
int u,v,next;
};
Edge g[200010];
int n,m;
int first[10010],num[10010];
int mov[10010],val[10010];
int vis[10010];
int tot,team;
long long ans , sum;
void addedge(int u,int v)
{
tot++;
g[tot].u = u; g[tot].v = v;
g[tot].next = first[u];
first[u] = tot;
}
void init()
{
for(int i = 1; i <= n; i++)
first[i] = -1;
for(int i = 1; i <= n; i++)
num[i] = 0;
for(int i = 1; i <= n; i++)
vis[i] = 0;
tot = 0;
}
queue < int > q;
void del()
{
for(int i = 1; i <= n; i++)
{
if(num[i] <= 1)
q.push(i);
}
while(!q.empty())
{
int u = q.front(); q.pop();
vis[u] = 1;
for(int i = first[u]; i != -1; i = g[i].next)
{
int v = g[i].v;
if(vis[v]) continue;
num[v]--;
if(num[v] <= 1)
q.push(v);
}
}
}
void dfs( int u)
{
vis[u] = 1;
team ++;
sum += val[u];
for(int i = first[u]; i != -1; i = g[i].next)
{
int v = g[i].v;
if(vis[v]) continue;
dfs(v);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i = 1; i <= n; i++) scanf("%d",&val[i]);
int u,v;
for(int i = 1; i <= m; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
num[u]++;
num[v]++;
}
del();
ans = 0;
for(int i = 1; i <= n; i++)
{
if(vis[i]) continue;
team = 0;
sum = 0;
dfs(i);
if(team%2!=0 && team > 2)
ans += sum;
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: