1952: [Sdoi2010]城市规划

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 73  Solved: 23
[Submit][Status][Discuss]

Description

小猪iPig来到了一个叫做pigsty的城市里,pigsty是一座专门为小猪所准备的城市,城市里面一共有n个小区给小猪们居住,并且存在许多条无向边连接着许多小区。因为这里是一个和谐的城市,所以小猪iPig准备在这个城市里面度过他的余生。若干年之后小猪iPig当上了规划局长,这件事令他非常开心。不过与此同时pigsty城市里面出现了许多反和谐主义者,他们已经厌烦了这样和谐的生活,在城市里到处闹事。小猪iPig为了更好地控制局面,他把城市改造成了另外一个样子:iPig把道路全部摧毁之后重新修建了m条无向边,并且保证每一个小区最多存在于一个由无向边组成的环中。 iPig以为这样做就让那些反和谐主义者不敢继续猖狂下去了,谁知到在新的城市道路修建好以后反和谐主义者宣言要对城市的小区进行一次洗脑!这下可麻烦了,iPig赶紧收集了许多的情报。iPig给每个小区标记了一个和谐值HX_i,用它来表示第i个小区的和谐程度。通过地下消息iPig又得知那些反和谐主义者进攻时有个规律:他们会选择若干个小区下手,这些小区都派一只猪过去,把这些小区的和谐值归零。在这个过程中,每个选择的小区所直接连接着的几个小区都派了一只猪去看守——以防被警猪给干扰。这个计划看似完美但是还是存在一个漏洞:因为人员之间都是在网络上认识的,互相没有见过面,为了防止不必要的麻烦(认错猪之类),每个小区最多只会有一头猪存在。 iPig突然感到了莫大的压力,他想知道在最坏情况下会丢失多少和谐值。但是不懂计算机的他不知道应该怎样计算。你能帮帮他吗?

Input

输入第一行有两个整数n和m,表示pigsty城市里面有n个小区,在iPig修整城市后有m条无向边连接着n个小区。接下来一行有n个正整数,第i个正整数HX_i表示第i个小区的和谐值为HX_i。接下来m行,每行两个正整数a和b(1<=a,b<=n),表示存在一条连接着小区a和小区 b的无向边。

Output

输出只有一行一个整数,表示最坏情况下损失的和谐值为多少。

Sample Input

9 9
2 2 3 4 1 2 3 10 11
1 2
2 3
1 3
3 5
5 4
5 6
4 7
6 7
8 9

Sample Output

17

【样例解释】
反和谐主义者选择的小区分别是小区3(看守的小区是小区1、小区2和小区5)、小区7(看守的小区是小区4和小区6)和小区9(看守的小区是小区8),这样会损失的总和谐值为3+3+11=17。
或者选择的小区分别是小区1(看守的小区是小区2和小区3)、小区4(看守的小区是小区5和小区7)和小区9(看守的小区是小区8),这样会损失的总和谐值为2+4+11=17。
如果同时选择小区3、小区4和小区9,虽然损失的总和谐值为18,但是小区3和小区4都要派猪来看守小区5,这不符合条件,故此方案不可行。

【数据约定】
对于20%的数据,保证每个点不存在于任何一个环中;
对于另外30%的数据,保证图中只存在一个环;
对于100%的数据,有N<=1000000,M<=2000000,所有的权值不超过1000。

HINT

Source

Solution

这是一道坑题,测试数据有误,标算有误,所以想要AC需要和标算错的一样 详见Discuss

询问了AC此题的Claris,得到的回复是:

说说正确做法:

仍旧是仙人掌DP,这里的话是仙人掌森林,不过原理是一样的e

求解最大点权独立集,然后仔细读样例发现,这里的“独立集”不同于平常的独立集,即不能选中间隔着一个的两个点

那么对于正常的求解方法是dp[i][0/1]表示当前到i位,选或不选的答案,这里就带限制的dp[i][0/1/2]去进行dp即可,转移是类似的

对仙人掌的处理方法一样是找环,拆环单独DP

Code

这里提供自己的正确做法(WA3组(数据有误)AC其余)

除discuss中提及的3组全A,并与提及的3组的正确答案相吻合

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{int x=0,f=1; char ch=getchar();while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}return x*f;
}
#define maxn 1000100
struct EdgeNode{int to,next;}edge[maxn<<2];
int head[maxn],cnt;
void add(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void insert(int u,int v) {add(u,v); add(v,u);}
int deep[maxn],fa[maxn],dfn[maxn],low[maxn],dp1[maxn][3],dp2[maxn][3],ring[maxn],HX[maxn],t;
int n,m,ans;void CactusDP(int st,int tt)
{ring[1]=tt; int zz=1;while (ring[zz]!=st) {ring[zz+1]=fa[ring[zz]]; zz++;}//printf("Num=%d  :",zz);//for (int i=1; i<=zz; i++) printf("%d ->",ring[i]); printf("\n");int f0=0,f1=0,f2=0;for (int opt=0; opt<=2; opt++){dp2[1][0]=dp2[1][1]=dp2[1][2]=0;dp2[1][opt]=dp1[tt][opt];if (opt==2) dp2[1][1]=dp2[1][2];for (int i=2; i<=zz; i++)dp2[i][0]=dp2[i-1][2]+dp1[ring[i]][0],dp2[i][1]=max(max(dp2[i-1][1],dp2[i-1][0])+dp1[ring[i]][2],dp2[i-1][1]+dp1[ring[i]][1]),dp2[i][2]=max(dp2[i-1][1],dp2[i-1][2])+dp1[ring[i]][2];if (opt==0) f1=max(f1,dp2[zz][2]);if (opt==1) f1=max(f1,dp2[zz][1]),f2=max(f2,dp2[zz][2]);if (opt==2) f1=max(f1,dp2[zz][1]),f0=max(f0,dp2[zz][0]),f2=max(f2,dp2[zz][2]);            }dp1[st][0]=f0; dp1[st][1]=f1; dp1[st][2]=f2;
}void TreeDP(int now)
{dfn[now]=low[now]=++t; dp1[now][2]=0; dp1[now][0]=HX[now]; int maxx=0;for (int i=head[now]; i; i=edge[i].next)if (edge[i].to!=fa[now]){if (deep[edge[i].to]) {low[now]=min(dfn[edge[i].to],low[now]); continue;}fa[edge[i].to]=now; deep[edge[i].to]=deep[now]+1;TreeDP(edge[i].to);if (low[edge[i].to]>low[now])dp1[now][2]+=max(dp1[edge[i].to][1],dp1[edge[i].to][2]),dp1[now][0]+=dp1[edge[i].to][2],maxx=max(maxx,dp1[edge[i].to][0]-max(dp1[edge[i].to][1],dp1[edge[i].to][2]));low[now]=min(low[now],low[edge[i].to]);}dp1[now][1]=maxx+dp1[now][2];for (int i=head[now]; i; i=edge[i].next)if (low[edge[i].to]==dfn[now] && edge[i].to!=fa[now] && deep[edge[i].to]!=deep[now]+1)CactusDP(now,edge[i].to);
}void Freopen() {freopen("area.in","r",stdin); freopen("area.out","w",stdout);}
void Fclose() {fclose(stdin); fclose(stdout);}int main()
{//Freopen();n=read(),m=read();for (int i=1; i<=n; i++) HX[i]=read();for (int u,v,i=1; i<=m; i++) u=read(),v=read(),insert(u,v);for (int i=1; i<=n; i++) if (!dfn[i]) {fa[i]=i,deep[i]=1; TreeDP(i); ans+=max(dp1[i][0],max(dp1[i][1],dp1[i][2]));}printf("%d\n",ans);//Fclose();return 0;
}

以及可A的标程,显然标程的判环是有些问题的

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std; const int N = 1000500, inf = ~0U >> 1; #define forEdges(iter,u) for(edge* iter = e[u]; iter; iter = iter->n)
struct edge { int t; edge *n; } ebf[N << 2], *e[N], *ec = ebf; int weight[N], n;
int dfn[N], low[N], S[N], sTop, dTime;
int f[N][3], rf[N][3], id[N], opt[N]; inline void updateN (int &x, int y) { if (x > y) x = y; }
inline void updateX (int &x, int y) { if (x < y) x = y; } inline void dfs (int u, int au)
{ int v; dfn[u] = low[u] = ++dTime, S[++sTop] = u; forEdges(it, u) if ((v = it->t) != au) if (!dfn[v]) dfs(v, u), updateN(low[u], low[v]); else updateN(low[u], dfn[v]); int maxDelt(0); f[u][2] = 0, f[u][0] = weight[u]; forEdges(it, u) if ((v = it->t) != au && low[v] > dfn[u]) // Sons
    { f[u][2] += max(f[v][1], f[v][2]); f[u][0] += f[v][2]; updateX(maxDelt, f[v][0] - max(f[v][1], f[v][2])); } f[u][1] = f[u][2] + maxDelt; forEdges(it, u) if (low[it->t] == dfn[u]) // A ring
    { int rs = 0; while (S[sTop] != u) id[++rs] = S[sTop--]; id[++rs] = u; /* RingDP : Line 53 .. 55 */int f0 = 0, f1 = 0, f2 = 0; for (int st = 0; st <= 2; ++st) { rf[1][0] = rf[1][1] = rf[1][2] = 0; rf[1][st] = f[id[1]][st]; if (st == 2) rf[1][1] = rf[1][2]; for (int i = 2; i <= rs; ++i) { //RingDP rf[i][0] = f[id[i]][0] + rf[i - 1][2]; rf[i][1] = max(f[id[i]][2] + max(rf[i - 1][0], rf[i - 1][1]), f[id[i]][1] + rf[i - 1][1]); rf[i][2] = f[id[i]][2] + max(rf[i - 1][1], rf[i - 1][2]); } switch (st) { case 0 : updateX(f1, rf[rs][2]); break; //!! case 1 : updateX(f1, rf[rs][1]), updateX(f2, rf[rs][2]); break; case 2 : updateX(f0, rf[rs][0]), updateX(f1, rf[rs][1]), updateX(f2, rf[rs][2]); break; } } f[u][0] = f0, f[u][1] = f1, f[u][2] = f2; } if (dfn[u] == low[u]) while (S[sTop + 1] != u) --sTop; opt[u] = max(f[u][0], max(f[u][1], f[u][2]));
} int main ()
{ int m, a, b; // freopen("area.in", "r", stdin); // freopen("area.out", "w", stdout); scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", weight + i); while (m--) { scanf("%d%d", &a, &b); *ec = (edge){b, e[a]}; e[a] = ec++; *ec = (edge){a, e[b]}; e[b] = ec++; } int res = 0; for (int i = 1; i <= n; ++i) if (!dfn[i]) dfs(i, 0), res += opt[i]; //A Connected Component printf("%d\n", res); return 0;
}

std

开荒做这种大坑,简直了= =||

转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5596732.html

【BZOJ-1952】城市规划 [坑题] 仙人掌DP + 最大点权独立集(改)相关推荐

  1. hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)...

    转载:http://blog.csdn.net/cold__v__moon/article/details/7924269 /* 这道题和方格取数2相似,是在方格取数2的基础上的变形.方格取数2解法: ...

  2. POJ1466 最大点权独立集

    题意:       给你n个人,再给你每个人都喜欢哪些人,让你找到一个最大的集合数,要求这个集合里面任意两个人都不喜欢彼此. 思路:       直接就是在问最大点权独立集元素个数,没啥解释的一遍二分 ...

  3. [网络流][最大点权独立集] 方格取数

    预备知识: 点覆盖集:无向图G的一个点集,使得该图中所有边都至少有一个端点在该集合内. 最小点权覆盖集:在带点权无向图G中,点权之和最小的覆盖集. 点独立集:无向图G的一个点集,使得任两个在该集合中的 ...

  4. HDU 1569 最大点权独立集

     最大点权独立集与最小点权覆盖是对偶问题,这里先介绍最小点权覆盖的解法. 最小点权覆盖问题是指,给出一张二分图,二分图的每个节点带有一个点权,要求从中选出若干节点,使得这些节点能够覆盖二分图中所有的 ...

  5. [最大点权独立集]AcWing 2326. 王者之剑

    题目:AcWing 2326. 王者之剑 分析: 本题的三个性质: 只能在偶数时间取宝石 相邻格子不能同时取 将棋盘黑白染色组成二分图之后,独立集跟原题的合法方案一一对应 所以本题就是求一个二分图的最 ...

  6. [学习笔记]最小割之最小点权覆盖最大点权独立集

    最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...

  7. POJ3692 最大点权独立集元素个数

    题意:      n个男孩和m个女孩,给你他们谁和谁彼此了解,问你要找到一个集合,使得这个集合中的男孩和女孩相互了解,并且人数最多. 思路:      简单题目,其实就是在求最大点权独立集元素个数,先 ...

  8. hdu 1569 方格取数(2) 最大点权独立集

    二分图. 最大点权独立集=总权-最小点权覆盖集. 哪位大神能给一些二分图 最大点权独立集等等 的相关资料!!!!!跪谢 用网络流求解最小点权覆盖集即可,建图不讲了. #include<cstdi ...

  9. [luoguP2774] 方格取数问题(最大点权独立集)

    传送门 引入两个概念: 最小点权覆盖集:满足每一条边的两个端点至少选一个的最小权点集. 最大点权独立集:满足每一条边的两个端点最多选一个的最大权点集. 现在对网格染色,使得相邻两点颜色不同,之后把两个 ...

最新文章

  1. MySql 密码忘记了,不用重装
  2. Bootstrap响应式与自适应区别
  3. [zz]用U盘装win7/XP系统的操作[图解]
  4. 修改场景默认pawn的方法
  5. oracle sql 查询优化器,基于ORACLE成本优化器的SQL查询优化分析与应用
  6. oracle 二进制与运算,Oracle怎么操作进行二进制的比对
  7. autofac获取全局Container
  8. 《深入理解Java虚拟机:JVM高级特性与最佳实践》 (第3版)周志明 著
  9. Xutils-Android中数据存储和网络传输的框架
  10. html5 小车动画_html5 echarts汽车仪表盘图表动画特效
  11. 洛谷 P2672 推销员 解题报告
  12. 左偏树(XJT Love Trees,玲珑杯 Round#8 C lonlife 1081)
  13. python爬斗鱼直播房间名和主播名_python3爬取斗鱼某些版块的主播人气
  14. 开源生态|打造活力开源社区,共建开源新生态!
  15. Python 安装PyQt5失败:Permission denied:d3dcompiler_47.dll
  16. FM33LC02X FreeRTOS MDK 移植记录总结
  17. matlab绘图去白边
  18. opengles的双PBO
  19. 图形开发——显卡学习
  20. 复现上篇文章故障得知:网卡错误56,Windows 仍在设置此设备的类配置的原因

热门文章

  1. showcase basketball stadium
  2. jQuery源码解析(2)—— Callback、Deferred异步编程
  3. 用简单的语言描述C++ 是什么?
  4. Python随手记—各种方法的使用
  5. django的单例模式和url分发
  6. 爬虫实践---电影排行榜和图片批量下载
  7. 从统计代码来谈JS加载的优化
  8. 第十四节(接口(行为))
  9. 创建维护计划时,提示“代理XP”组件已作为此服务器安全配置的一部分被关闭...
  10. 瑞星杀毒全面免费 请下载