题意:给你n个点,m条边,包括有向边与无向边,每条边都有一个权值。在每个点上都有一个人,他可以走与这个点直接相连的所有边中任意一条边一次,并且得到这个权值,就不能走了,注意这条路也只能被一个人走。问最大的权值和是多少

首先我们可以想到每个点直接走与其相连权值最大的可以走的点,不一定是最优的,因为可能:1双向走到2权值为7,1单向走到3权值为6,这时1走到3才是最优的。但是我们可以观察得到对于单向边,我们确定起点,对于双向边,我们可以寻找两个点中最优的一个点,按照这样贪心就可以。

首先我们按照权值排序,还有就是我们要记录这个点是否被用过,但是根据之前的想法,我们可以知道有些时候不能马上确定点,但是可以确定两点找一个。因此我们可以标记0代表没用过,1代表两个点中取一个点(其实是x个点中取x-1个点),2代表已经使用。因此我们可以想到对于单向边,确定点值为2。出现双向边,如果是(0 0)(0 1)我们只能确定为(1 1),但是出现(1 1)(0 2)(1 2)确定点值为(2 2)。(这儿有个小bug)

现在我们要注意几个问题,首先就是如果点1点2是双向边,点2点3是双向边,则我们就要在 点1点2点3 中选两个点,所以需要并查集维护连通块,接着如果出现点1点2,点3点4,再出现点2点3,则我们就要维护两个连通块合并。最后我们可以每次都加上这个权值,再判断如果不能加这条边时就减去这个权值,这样并查集就不需要存权值了

通过这个题我学到了,如果我们得到的多个值暂时不能确定那个值是最优的,那么我们可以先假设每个点都是最优的再存下来,接着根据后面的条件解决这个问题

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=;
const int Max2=;
struct node
{
int u,v,d,c;
} edg[Max2];
int fat[Max],vis[Max];//缩点存不确定的点 标记0 1 2
void Init(int n)
{
for(int i=; i<n+; ++i)
{
fat[i]=i;
vis[i]=;
}
return;
}
int Find(int x)
{
if(x==fat[x])
return fat[x];
return fat[x]=Find(fat[x]);
}
bool cmp(struct node p1,struct node p2)//价值排序,贪心
{
return p1.c>p2.c;
}
int Union(int x,int y,int v)//此两点不确定,进行并查集的合并
{
int x1=Find(x);
int y1=Find(y);
if(x1==y1)
return ;
fat[x1]=y1;
vis[x]=vis[y]=;
return ;
}
void Jud(int n,int x)
{
if(vis[x]==)//注意
{
vis[x]=;
return;
}
int x1=Find(x);
for(int i=; i<=n; ++i)
{
if(Find(i)==x1)
vis[i]=;
}
return;
}
int Solve(int n,int m)
{
int ans=;
sort(edg,edg+m,cmp);
for(int i=; i<m; ++i)
{
ans+=edg[i].c;//每次都加上
if(edg[i].d==)//双向
{
if(!vis[edg[i].u]&&!vis[edg[i].v]||!vis[edg[i].u]&&vis[edg[i].v]==||vis[edg[i].u]==&&!vis[edg[i].v])//放入连通块
Union(edg[i].u,edg[i].v,edg[i].c);
else if(vis[edg[i].u]!=||vis[edg[i].v]!=)//此处所有连通块都确定了
{
if(vis[edg[i].u]==&&vis[edg[i].v]==)//可能不同连通块
{
if(!Union(edg[i].u,edg[i].v,edg[i].c))
Jud(n,edg[i].u);
}
else if(vis[edg[i].u]!=)
Jud(n,edg[i].u);
else
Jud(n,edg[i].v);
}
else
ans-=edg[i].c;
}
else
{
if(vis[edg[i].u]!=)
Jud(n,edg[i].u);
else
ans-=edg[i].c;
}
}
return ans;
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
Init(n);
for(int i=; i<m; ++i)
scanf("%d %d %d %d",&edg[i].u,&edg[i].v,&edg[i].d,&edg[i].c);
printf("%d\n",Solve(n,m));
}
return ;
}

HDU 2480 Steal the Treasure (并查集+贪心)的更多相关文章

  1. HDU 1598 find the most comfortable road 并查集+贪心

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1598 find the most comfortable road Time Limit: 1000 ...

  2. [POJ2054]Color a Tree (并查集+贪心)

    POJ终于修好啦 题意 和UVA1205是同一题,在洛谷上是紫题 有一棵树,需要给其所有节点染色,每个点染色所需的时间是一样的都是11.给每个点染色,还有一个开销“当前时间×ci×ci”,cici是每 ...

  3. HDU HDU1558 Segment set(并查集+判断线段相交)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558 解题报告:首先如果两条线段有交点的话,这两条线段在一个集合内,如果a跟b在一个集合内,b跟c在一 ...

  4. hdu 1257 小希的迷宫 并查集

    小希的迷宫 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1272 D ...

  5. hdu 4424 & zoj 3659 Conquer a New Region (并查集 + 贪心)

    Conquer a New Region Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...

  6. hdu 3635 Dragon Balls(并查集应用)

    Problem Description Five hundred years later, the number of dragon balls will increase unexpectedly, ...

  7. <hdu - 1272> 小希的迷宫 并查集问题 (注意特殊情况)

     本题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272 Problem Description: 上次Gardon的迷宫城堡小希玩了很久(见Probl ...

  8. HDU 4496 D-City(逆向并查集)

    http://acm.hdu.edu.cn/showproblem.php?pid=4496 题意: 给出n个顶点m条边的图,每次选择一条边删去,求每次删边后的连通块个数. 思路: 离线处理删边,从后 ...

  9. HDU 3407.Zjnu Stadium 加权并查集

    Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

随机推荐

  1. 从网上搜索到的一些关于pcap源代码,入门级的

    /*pcap_1.c*/ #include <stdio.h>#include <stdlib.h>#include <pcap.h>  /* 如果没有pcap的系 ...

  2. ES6学习笔记(二)——字符串扩展

    相信很多人也和我一样,不喜欢这样循规蹈矩的逐条去学习语法,很枯燥乏味.主要是这样学完一遍之后,没过一段时间就忘到九霄云外了.不如实际用到的时候研究它记得牢靠,所以我就整理成笔记,加深记忆的同时便于复习 ...

  3. python3爬虫-分析Ajax,抓取今日头条街拍美图

    # coding=utf-8 from urllib.parse import urlencode import requests from requests.exceptions import Re ...

  4. 002-基本业务搭建【日志,工具类dbutils,dbcp等使用】

    一.需求分析 1.1.概述 1.用户进入“客户管理”,通过列表方式查看用户: 2.客户名称,模糊查询用户列表 3.客户名称,可查看客户详细信息 4.新增.编辑.删除功能等 二.系统设计 需要对原始需求 ...

  5. 《Deep learning》第四章——数值计算

    数值计算 机器学习算法通常需要大量的数值计算.这通常是指通过迭代过程更新解的估计值来解决数学问题的算法,而不是通过解析过程推导出公式来提供正确解的方法.常见的操作包括优化(找到最小化或最大化函数值的参 ...

  6. cut命令学习

    cut最基本的用法: -f 列号:提取第几列 -d 分隔符:按照指定分隔符分割列(默认是制表符tab) 测试用例:(制表符)

  7. 爬虫五 Beautifulsoup模块

    一 介绍 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你 ...

  8. ZOJ 3958 Cooking Competition 【水】

    题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3958 AC代码 #include <cstdio> ...

  9. 【转】dmesg 时间转换

    dmesg 时间转换 dmesg 输出的格式不易查看,可以通过命令进行转换. 记录如下: 时间查看: date -d "1970-01-01 UTC `echo "$(date + ...

  10. MySQL 数据库怎样把一个表的数据插入到另一个表

         web开发中,我们经常需要将一个表的数据插入到另外一个表,有时还需要指定导入字段,设置只需要导入目标表中不存在的记录,虽然这些都可以在程序中拆分成简单sql来实现,但是用一个sql的话,会节 ...