题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5438

题面:

Ponds

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1308    Accepted Submission(s): 439

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 .

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

Input
The first line of input will contain a number T(1≤T≤30) which is the number of test cases.

For each test case, the first line contains two number separated by a blank. One is the number p(1≤p≤104) which represents the number of ponds she owns, and the other is the number m(1≤m≤105) which represents the number of pipes.

The next line contains p numbers v1,...,vp , where vi(1≤vi≤108) indicating the value of pond i .

Each of the last m lines contain two numbers a and b , which indicates that pond a and pond b are connected by a pipe.

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

题目大意:

给定一些池塘,池塘之间连有一些管道。要求将不连管道或者只连一根管道的池塘消去,问最后剩下连在一起且池塘个数为奇数的池塘权值总和。

解题:

比赛的时候,以为是什么奇环,后来发现又不是,思路整体跑偏了。正确的解法是,通过bfs或者dfs不断消去度数为1的点,消完之后,再用dfs找联通块即可。以下提供两种解法,实际上没什么实质差别,复杂度都为O(m),因为每条边最多遍历一次。

解法一:

dfs+dfs

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
#define LL long long
int pond[10010];
//邻接表
struct edge
{int next,to,vis;//下一条边序号,到哪个点,边是否被断开
}store[200010];
int head[10010],cnt,degree[10010],num;//head存储每个点连向的第一条边的存储下标,-1代表该点当前已经没有边了
//cnt加边的下标,degree度数,num联通块中的块数
bool vist[10010];//数联通块时的标记
LL sum;//存储联通块的总和
//加边
void addedge(int a,int b)
{store[cnt].to=b;store[cnt].next=head[a];store[cnt].vis=false;head[a]=cnt++;
}
//消去池塘
void dfs(int x)
{int tmp;tmp=head[x];degree[x]=0;//还未到最后一条边while(tmp!=-1){if(degree[store[tmp].to]){//tmp和tmp^1代表相邻两条边store[tmp].vis=store[tmp^1].vis=true;degree[store[tmp].to]--;//如果度数为1,继续搜索if(degree[store[tmp].to]==1)dfs(store[tmp].to);}//移向下一条边tmp=store[tmp].next;}return;
}
void dfs2(int x)
{int tmp,v;vist[x]=1;tmp=head[x];while(tmp!=-1){//如果这条边还没断开if(!store[tmp].vis){v=store[tmp].to;if(!vist[v]&°ree[v]){num++;sum+=pond[v];dfs2(v);}}tmp=store[tmp].next;}
}
int main()
{int t,p,m,u,v,tmp,cas=1;LL ans;scanf("%d",&t);while(t--){scanf("%d%d",&p,&m);memset(head,-1,sizeof(head));memset(degree,0,sizeof(degree));memset(vist,0,sizeof(vist));cnt=ans=0;for(int i=1;i<=p;i++)scanf("%d",&pond[i]);for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);degree[u]++;degree[v]++;}//搜索度数为1的池塘for(int i=1;i<=p;i++)if(degree[i]==1)dfs(i);//统计结果for(int i=1;i<=p;i++){if(degree[i]&&!vist[i]){sum=pond[i];num=1;dfs2(i);if(num%2)ans+=sum;}}printf("%lld\n",ans);}return 0;
}

解法二:

bfs+dfs

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int pond[10010];
struct edge
{int next,to;
}store[200010];
int head[10010],cnt,degree[10010];
bool vist[10010],cut_off[200010];
long long sum;
int num;
queue <int> qe;
inline void addedge(int a,int b)
{store[cnt].to=b;store[cnt].next=head[a];head[a]=cnt++;
}
void bfs()
{int tmp,cur,v;while(!qe.empty()){cur=qe.front();qe.pop();tmp=head[cur];while(~tmp){v=store[tmp].to;if(degree[v]){cut_off[tmp]=cut_off[tmp^1]=1;degree[v]--;if(degree[v]==1){qe.push(v);degree[v]=0;}}tmp=store[tmp].next;}}
}
void dfs(int x)
{int tmp,v;vist[x]=1;tmp=head[x];while(tmp!=-1){if(!cut_off[tmp]){v=store[tmp].to;if(!vist[v]){num++;sum+=pond[v];dfs(v);}}tmp=store[tmp].next;}
}
int main()
{int t,p,m,u,v;long long  ans;scanf("%d",&t);while(t--){scanf("%d%d",&p,&m);memset(head,-1,sizeof(head));memset(degree,0,sizeof(degree));memset(vist,0,sizeof(vist));memset(cut_off,0,sizeof(cut_off));cnt=0,ans=0;for(int i=1;i<=p;i++)scanf("%d",&pond[i]);for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);degree[u]++;degree[v]++;}for(int i=1;i<=p;i++)if(degree[i]==1)qe.push(i),degree[i]=0;bfs();for(int i=1;i<=p;i++){if(degree[i]&&!vist[i]){sum=pond[i];num=1;dfs(i);if(num%2)ans+=sum;}}printf("%lld\n",ans);}return 0;
}

HDU 5438 Ponds (搜索)相关推荐

  1. hdu 5438 Ponds 拓扑排序

    Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem ...

  2. HDU - 5438 Ponds 拓扑 dfs

    题意 在一个图中 给出了每个点得权值和连边 想要尽可能删除一些联通的点数小于2的点 删完后 求最后剩下联通块内点得数量是奇数的权值和 分析 本题由于在删除点得过程中需要考虑 当把当前点删除后 其联通的 ...

  3. hdu 5439 Ponds(长春网络赛——拓扑排序+搜索)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5438 Ponds Time Limit: 1500/1000 MS (Java/Others)     ...

  4. hdu 1043 Eight 搜索,哈希

    很早之前做过,总结一下康拓展开哈希大法.当初要是懂了这玩意北京网赛那题一定能出.... http://acm.hdu.edu.cn/showproblem.php?pid=1043题目链接 http: ...

  5. G - 变形课 HDU - 1181(搜索之dfs)

    呃-变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个统一规律:如果咒语是以a开头b结尾的一个单词,那么 ...

  6. 蜘蛛牌 HDU - 1584(搜索——达到先让某些段先结合,达最优解)

    题意: 一排杂乱的牌,牌间距为1,每次移动只能将小的牌,移动到较大牌上,最终使得牌从小到大排好在一堆.问移动的最小距离. 题目: 蜘蛛牌是windows xp操作系统自带的一款纸牌游戏,游戏规则是这样 ...

  7. HDU 1026 广度优先搜索,BFS+路径的记录

    哎~~花了半天的时间写了一个DFS的程序,结果无情的limit time exceed,然后到网上搜了一下,居然用的是BFS 一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是& ...

  8. HDU 4435 charge-station (搜索+YY)

    题意:有一个人要从1点出发把所有点遍历一遍并且最后能回到1点,其中每隔d距离就要加一次油,现在我们在各个点设一些加油站(1点必须设),且每隔点建加油站的费用最小为2^(i-1),求满足条件下的最小花费 ...

  9. hdu 4090(搜索+可行性剪枝)

    解题思路:这道题一开始我想用bfs,但这道题我感觉难的是每次消除后,怎么往下往左移动.此外还有就是要剪枝,不然是过不了的,可采用可行性剪枝,即当前的得分加上当前状态下可能得到的最大分,如果还不能够达到 ...

最新文章

  1. Qt5.3.1 MinGW482 release静态版编译结果、过程及QtCreator配置(转)
  2. 【干货】这10个Liunx命令能提高50%的工作效率
  3. [云炬ThinkPython阅读笔记]3.1 函数调用
  4. android TextView 的setTextSize方法的使用
  5. 云服务器 ECS CentOS 7配置默认防火墙 Firewall
  6. 简单高效搞定---迁移学习
  7. Visual Studio 2019 C# 断点调试 凯撒密码,单码密码实现
  8. sql server的数据同步
  9. mybatis mysql net教程_MyBatis 教程
  10. MP288MP280清零软件
  11. ME525+ Defy+ 刷机指南[zz]
  12. PHP判断PC浏览器与手机浏览器的方法
  13. Similarity-Preserving Knowledge Distillation
  14. 聚美优品启动上市,真的那么赚钱吗?
  15. springboot中static下的图片404
  16. 数组统计问题(统计各学生的优秀率及格率)C语言
  17. 好记性不如烂笔头(一)——局域网可以Ping通,但Socket无法连接
  18. Java自动识别身份证信息
  19. .dll文件有什么用?
  20. [SRM] 10 CCZ的诗

热门文章

  1. 优秀Android开源项目大全
  2. ActiveSync 3.7
  3. 解读领跑全国的区块链发展“北京方案”:设专项基金,构建开源生态
  4. 搜狐2009年第二季度财报电话会议实录(含我的评论)
  5. 婚恋交友app源码,礼物功能如何实现
  6. 《个人信息保护条例》
  7. Tomcat无法启动卡在Artifact is being deployed, please wait...
  8. 关于FPV图传系统时延讨论
  9. PMP项目管理-[第十章]沟通管理
  10. C语言编写通讯录系统