【BZOJ-1952】城市规划 [坑题] 仙人掌DP + 最大点权独立集(改)
1952: [Sdoi2010]城市规划
Time Limit: 10 Sec Memory Limit: 128 MB
Submit:
73 Solved: 23
[Submit][Status][Discuss]
Description
iPig以为这样做就让那些反和谐主义者不敢继续猖狂下去了,谁知到在新的城市道路修建好以后反和谐主义者宣言要对城市的小区进行一次洗脑!这下可麻烦了,iPig赶紧收集了许多的情报。iPig给每个小区标记了一个和谐值HX_i,用它来表示第i个小区的和谐程度。通过地下消息iPig又得知那些反和谐主义者进攻时有个规律:他们会选择若干个小区下手,这些小区都派一只猪过去,把这些小区的和谐值归零。在这个过程中,每个选择的小区所直接连接着的几个小区都派了一只猪去看守——以防被警猪给干扰。这个计划看似完美但是还是存在一个漏洞:因为人员之间都是在网络上认识的,互相没有见过面,为了防止不必要的麻烦(认错猪之类),每个小区最多只会有一头猪存在。
iPig突然感到了莫大的压力,他想知道在最坏情况下会丢失多少和谐值。但是不懂计算机的他不知道应该怎样计算。你能帮帮他吗?
Input
b的无向边。
Output
Sample Input
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
【样例解释】
反和谐主义者选择的小区分别是小区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=,f=; char ch=getchar();
- while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
- while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
- return x*f;
- }
- #define maxn 1000100
- struct EdgeNode{int to,next;}edge[maxn<<];
- 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][],dp2[maxn][],ring[maxn],HX[maxn],t;
- int n,m,ans;
- void CactusDP(int st,int tt)
- {
- ring[]=tt; int zz=;
- while (ring[zz]!=st) {ring[zz+]=fa[ring[zz]]; zz++;}
- //printf("Num=%d :",zz);
- //for (int i=1; i<=zz; i++) printf("%d ->",ring[i]); printf("\n");
- int f0=,f1=,f2=;
- for (int opt=; opt<=; opt++)
- {
- dp2[][]=dp2[][]=dp2[][]=;
- dp2[][opt]=dp1[tt][opt];
- if (opt==) dp2[][]=dp2[][];
- for (int i=; i<=zz; i++)
- dp2[i][]=dp2[i-][]+dp1[ring[i]][],
- dp2[i][]=max(max(dp2[i-][],dp2[i-][])+dp1[ring[i]][],dp2[i-][]+dp1[ring[i]][]),
- dp2[i][]=max(dp2[i-][],dp2[i-][])+dp1[ring[i]][];
- if (opt==) f1=max(f1,dp2[zz][]);
- if (opt==) f1=max(f1,dp2[zz][]),f2=max(f2,dp2[zz][]);
- if (opt==) f1=max(f1,dp2[zz][]),f0=max(f0,dp2[zz][]),f2=max(f2,dp2[zz][]);
- }
- dp1[st][]=f0; dp1[st][]=f1; dp1[st][]=f2;
- }
- void TreeDP(int now)
- {
- dfn[now]=low[now]=++t;
- dp1[now][]=; dp1[now][]=HX[now]; int maxx=;
- 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]+;
- TreeDP(edge[i].to);
- if (low[edge[i].to]>low[now])
- dp1[now][]+=max(dp1[edge[i].to][],dp1[edge[i].to][]),
- dp1[now][]+=dp1[edge[i].to][],
- maxx=max(maxx,dp1[edge[i].to][]-max(dp1[edge[i].to][],dp1[edge[i].to][]));
- low[now]=min(low[now],low[edge[i].to]);
- }
- dp1[now][]=maxx+dp1[now][];
- 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]+)
- 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=; i<=n; i++) HX[i]=read();
- for (int u,v,i=; i<=m; i++) u=read(),v=read(),insert(u,v);
- for (int i=; i<=n; i++) if (!dfn[i]) {fa[i]=i,deep[i]=; TreeDP(i); ans+=max(dp1[i][],max(dp1[i][],dp1[i][]));}
- printf("%d\n",ans);
- //Fclose();
- return ;
- }
以及可A的标程,显然标程的判环是有些问题的
- #include <cstdio>
- #include <cstring>
- #include <vector>
- #include <algorithm>
- using namespace std;
- const int N = , inf = ~0U >> ;
- #define forEdges(iter,u) for(edge* iter = e[u]; iter; iter = iter->n)
- struct edge { int t; edge *n; }
- ebf[N << ], *e[N], *ec = ebf;
- int weight[N], n;
- int dfn[N], low[N], S[N], sTop, dTime;
- int f[N][], rf[N][], 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();
- f[u][] = , f[u][] = weight[u];
- forEdges(it, u) if ((v = it->t) != au && low[v] > dfn[u]) // Sons
- {
- f[u][] += max(f[v][], f[v][]);
- f[u][] += f[v][];
- updateX(maxDelt, f[v][] - max(f[v][], f[v][]));
- }
- f[u][] = f[u][] + maxDelt;
- forEdges(it, u) if (low[it->t] == dfn[u]) // A ring
- {
- int rs = ;
- while (S[sTop] != u) id[++rs] = S[sTop--];
- id[++rs] = u;
- /* RingDP : Line 53 .. 55 */
- int f0 = , f1 = , f2 = ;
- for (int st = ; st <= ; ++st)
- {
- rf[][] = rf[][] = rf[][] = ;
- rf[][st] = f[id[]][st];
- if (st == ) rf[][] = rf[][];
- for (int i = ; i <= rs; ++i)
- { //RingDP
- rf[i][] = f[id[i]][] + rf[i - ][];
- rf[i][] = max(f[id[i]][] + max(rf[i - ][], rf[i - ][]), f[id[i]][] + rf[i - ][]);
- rf[i][] = f[id[i]][] + max(rf[i - ][], rf[i - ][]);
- }
- switch (st)
- {
- case : updateX(f1, rf[rs][]); break; //!!
- case : updateX(f1, rf[rs][]), updateX(f2, rf[rs][]); break;
- case : updateX(f0, rf[rs][]), updateX(f1, rf[rs][]), updateX(f2, rf[rs][]); break;
- }
- }
- f[u][] = f0, f[u][] = f1, f[u][] = f2;
- }
- if (dfn[u] == low[u]) while (S[sTop + ] != u) --sTop;
- opt[u] = max(f[u][], max(f[u][], f[u][]));
- }
- int main ()
- {
- int m, a, b;
- // freopen("area.in", "r", stdin);
- // freopen("area.out", "w", stdout);
- scanf("%d%d", &n, &m);
- for (int i = ; 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 = ;
- for (int i = ; i <= n; ++i)
- if (!dfn[i]) dfs(i, ), res += opt[i]; //A Connected Component
- printf("%d\n", res);
- return ;
- }
std
开荒做这种大坑,简直了= =||
【BZOJ-1952】城市规划 [坑题] 仙人掌DP + 最大点权独立集(改)的更多相关文章
- BZOJ 1475 方格取数(二分图最大点权独立集)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1475 [题目大意] 给出一个n*n的方格,从中取一些不相邻的数字,使得和最大 [题解] ...
- HDU 1565 1569 方格取数(最大点权独立集)
HDU 1565 1569 方格取数(最大点权独立集) 题目链接 题意:中文题 思路:最大点权独立集 = 总权值 - 最小割 = 总权值 - 最大流 那么原图周围不能连边,那么就能够分成黑白棋盘.源点 ...
- LibreOJ #6007. 「网络流 24 题」方格取数 最小割 最大点权独立集 最大流
#6007. 「网络流 24 题」方格取数 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)
转载:http://blog.csdn.net/cold__v__moon/article/details/7924269 /* 这道题和方格取数2相似,是在方格取数2的基础上的变形. 方格取数2解法 ...
- HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]
嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
/** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...
- hdu1569 方格取数 求最大点权独立集
题意:一个方格n*m,取出一些点,要求两两不相邻,求最大和.思路:建图,相邻的点有一条边,则建立了一个二分图,求最大点权独立集(所取点两两无公共边,权值和最大),问题转化为求总权和-最小点权覆盖集(点 ...
- POJ1466 最大点权独立集
题意: 给你n个人,再给你每个人都喜欢哪些人,让你找到一个最大的集合数,要求这个集合里面任意两个人都不喜欢彼此. 思路: 直接就是在问最大点权独立集元素个数,没啥解释的一遍二分 ...
- HDU 1565 最大点权独立集
首先要明白图论的几个定义: 点覆盖.最小点覆盖: 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是“点” 覆盖了所有“边”.. 最小点覆盖(minimum vertex covering ...
随机推荐
- flask01 安装及初涉
一.安装 1.pip的安装 $ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py $ python get-pip.p ...
- java工程中的.classpath<转载>
第一部分:classpath是系统的环境变量,就是说JVM加载类的时候要按这个路径下去找,当然这个路径下可以有jar包,那么就是jar包里所有的class. eclipse build path是ec ...
- 启动Oracle
[oracle@redhat ~]$ su - oracle --“切换到oracle用户”Password:[oracle@redha ...
- BZOJ 1014 【JSOI2008】 火星人prefix
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- [转]向facebook学习,通过协程实现mysql查询的异步化
FROM : 通过协程实现mysql查询的异步化 前言 最近学习了赵海平的演讲,了解到facebook的mysql查询可以进行异步化,从而提高性能.由于facebook实现的比较早,他们不得不对php ...
- QT 记事本小程序
//mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <Q ...
- springmvc请求参数异常处理
接着上一篇<springmvc 通过异常增强返回给客户端统一格式>讲通过spring ControllerAdvice对各种异常进行拦截处理,统一格式返回给客户端. 接下来我们更精细的讲, ...
- PhoneGap: Android平台入门例子(Hello World)
Hello World Demo: http://docs.phonegap.com/en/2.0.0/guide_getting-started_android_index.md.html#Gett ...
- echarts .NET类库开源
前言: 2012年从长沙跑到深圳,2016年又从深圳回到长沙,兜兜转转一圈,又回到了原点.4年在深圳就呆了一家公司,回长沙也是因为深圳公司无力为继,长沙股东老板挽留,想想自己年纪也不小了.就回来了,在 ...
- webpack 插件: html-webpack-plugin
插件地址:https://www.npmjs.com/package/html-webpack-plugin 这个插件用来简化创建服务于 webpack bundle 的 HTML 文件,尤其是对于在 ...