题目大意

给定一个点数为 n n,边数为mm的图 G=(V,E) G=(V,E),改图的生成m满足存在一个 1 1至nn的排列 a1..an a_{1}..a_{n},使得:
∙∀(u,v)∈E,u<v \bullet\forall (u,v)\in E,u\lt v,满足 au>av a_u\gt a_v
∙∀1≤i<j≤n,ai<aj \bullet\forall 1\le i\lt j\le n,a_i\lt a_j满足 (i,j)∉E (i,j)\not\in E
说简单点就是该图由一个排列中的逆序对位置相连而成。
求该图中有多少非空点集,满足该点集同时为该图的独立集和覆盖集。

1≤n≤1000,0≤m≤n(n−1)2 1\le n\le1000,0\le m\le \frac{n(n-1)}{2}


题目分析

一般的独立集问题应该是NP问题。如果图是二分图,那么可以用最小覆盖集来解决。
但是在这题,题目中的图并不是二分图。所以将这题看成图来想是几乎不可解的(虽说我一看到独立集、覆盖集就有些小激动了)。
既然出题人给定了通过排列构造的图,那我们也应该将这题的图看成排列来想。
先考虑如何还原这个排列。我比赛时想了一个极其笨重的方法。就是将排列中每个数往比它小的数连边,然后做拓扑排序,依次从大到小填数字。
具体实现就是
1. ∀1≤u<v≤n,(u,v)∉E \forall1\le u\lt v\le n,(u,v)\notin E,这两个位置上的数在原排列一定是正序的,所以连有向边 (v,u) (v,u)。
2. ∀1≤u<v≤n,(u,v)∈E \forall1\le u\lt v\le n,(u,v)\in E,这两个位置上的数在原排列一定是逆序的,所以连有向边 (u,v) (u,v)。
然后我们做拓扑排序,拓扑序越前的位置,对应的数越大。
容易证明上述方法的正确性,由此也可以证明给定的图对应的合法排列只有一个。
这时我们可以转化问题了。我们发现所谓独立集,其实就是一段数互不为逆序对,那么就肯定是数列中的递增子序列。而所谓覆盖集,其实就是除了集合内位置上的数,其它位置上的数与集合内至少一个位置上的数成逆序对。
我们利用数形结合的思想考虑一下:

这是由排列构成的平面直角坐标系,横轴表示位置,纵轴表示值。先满足独立集的要求,即取递增的点,例如图中红点。接着满足覆盖集。我们发现能与一个点构成逆序对的点一定在该点左上或右下方。所以一个不属于独立集的点,如果在独立集中至少有一个逆序点,那它必须在图中黄色区域,这种区域由所有红点的左上角和右下角构成。
这样,独立集的相邻两点构成了许多长方形(这是独立集内点递增的好处)。我们再次转化上面所述的条件,就可以得到,一个独立集如果是覆盖集,当且仅当坐标系中没有任何非该集合的点位于白色区域。
于是题目转化为,求有多少递增子序列,相邻两点构成的长方形块内没有点(注意特殊考虑第1个点和第n个点的情况)。
这时我们增加点 (0,0) (0,0)和 (n+1,n+1) (n+1,n+1),我们用动态规划解决这个问题。
设 fi f_i表示当前考虑到位置 i i(集合内所有数位置小于等于ii),包括 i i点的独立覆盖集的个数。

suml,x,r,y(0≤l≤r≤n+1,0≤x≤y≤n+1)

sum_{l,x,r,y}(0\le l\le r\le n+1,0\le x\le y\le n+1)表示坐标系中左下顶点坐标为 (l,x) (l,x),右上顶点坐标为 (r,y) (r,y)的长方形内点的个数。这个数组可以用二维前缀和处理。
显然可得

fi=∑j=0j−1{fj|aj<ai,sumj,aj,i,ai=2}

f_i=\sum_{j=0}^{j-1}\{f_j|a_j 初值 f0=1 f_0=1,最后答案为 fn+1 f_{n+1}。

很高兴这道题在比赛上一次过了。让我开心一会。
其实这题主要就是考察模型的转化,还有一定的归纳总结。接着就是一个水dp了。
这是我在CSDN第一个博客,想写点有意义的题(然而对各位神犇来说还是太水了)。请大家多多关照。

代码实现

#include <iostream>
#include <cstdio>using namespace std;const int N=1005;
const int M=(N-1)*N>>1;
const int P=1000000007;int tov[M+1],next[M+1],f[N+1],a[N+1];
int last[N+1],que[N+1],deg[N+1];
int n,m,tot,ans,ord,head,tail;
bool edge[N+1][N+1];
int sum[N+1][N+1];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;
}void insert(int x,int y)
{tov[++tot]=y;next[tot]=last[x];last[x]=tot;deg[y]++;
}int main()
{freopen("senritsu.in","r",stdin);freopen("senritsu.out","w",stdout);n=read(),m=read();int x,y;for (int i=1;i<=m;i++){x=read(),y=read();edge[x][y]=true;edge[y][x]=true;if (x<y)insert(x,y);elseinsert(y,x);}for (int i=1;i<n;i++)for (int j=i+1;j<=n;j++)if (!edge[i][j])insert(j,i);head=0;tail=1;for (int i=1;i<=n;i++)if (!deg[i]){que[1]=i;break;}ord=n;int i;while (head!=tail){x=que[++head];a[x]=ord--;i=last[x];while (i){y=tov[i];deg[y]--;if (!deg[y])que[++tail]=y;i=next[i];}}a[0]=0;f[0]=1;a[n+1]=n+1;int tmp,get,j;sum[0][0]=1;for (i=1;i<=n;i++)sum[i][a[i]]=1;sum[n+1][n+1]=1;for (i=0;i<=n+1;i++)for (j=1;j<=n+1;j++)sum[i][j]+=sum[i][j-1];for (i=1;i<=n+1;i++)for (j=0;j<=n+1;j++)sum[i][j]+=sum[i-1][j];for (i=1;i<=n+1;i++)for (j=0;j<i;j++){if (a[i]<a[j])continue;tmp=sum[i][a[i]]-sum[i][a[j]]-1;get=sum[j][a[i]]-sum[j][a[j]];tmp-=get;if (!tmp)f[i]=(f[i]+f[j])%P;}printf("%d\n",f[n+1]);fclose(stdin);fclose(stdout);return 0;
}

[GDOI模拟2015.08.12]囚人的旋律相关推荐

  1. 4-4模拟赛 囚人的旋律——DP

    前置技能点:DP,上升子序列 如果你不知道上面的东西,请先行了解 start_of_题面 [问题描述] 被诅咒的监狱里流淌着囚人们的歌谣. 将罪恶的青春全部抹杀殆尽. "看守"执掌 ...

  2. NOIP2013模拟10.23囚人的旋律

    题目大意 给定一个逆序图,表示若a[i]>a[j](i<j)那么i向j连一条边(这里是给定边数),问有多少个选点方案,是的选定的点之间没有连边,没选定的点与选定的点中至少一个点有连边. 由 ...

  3. 【BZOJ4715】囚人的旋律

    题解: 思考了很久这个图的特点没有发现 看了题解瞬间醒悟原来要在序列上做 还原出这张图显然是O(N^2)可以做的 然后其实就比较简单了 首先为了满足独立集,我们需要保证所取元素递增 为了满足覆盖集,我 ...

  4. 【bzoj4715】囚人的旋律 dp

    题目描述 给你一个 $1\sim n$ 的排列 $a_i$ ,若 $i\le j$ 且 $a_i\ge a_j$ ,则 $i$ 到 $j$ 有一条边.现在给你这张图,求既是独立集(任意两个选定点都没有 ...

  5. dockone上2015.08 Docker有价值文章

    为什么80%的码农都做不了架构师?>>>    Docker入门与基础 [1] Docker入门实战, http://yuedu.baidu.com/ebook/d817967416 ...

  6. 2015年12月份学习总结,前端开发工程师的知识库指引

    本文摘录2015年12月份学习总结,创建日期:2016-01-03 14:01:01,有修改. 以下正文: 在9月份领到了一项任务是关于<前端开发工程师的知识库指引>,想了又想,而在我们现 ...

  7. 2015年职场人薪资惬意度调查报告

    2015年职场人薪资惬意度调查报告 想知道今年节后别人的工资涨了多少吗?想知道谈薪的时候薪水期望涨幅在多大的范围easy被企业接受吗? 想知道自己的薪资是什么水平.是"抱了大腿"还 ...

  8. 94-《纪元2205》游戏体会.(2015.11.12)

    <纪元2205>游戏体会 在游戏中,感受到了多重概念. 0.不要想当然的看问题. 1.生产能力包括:生产的时间效率.生产的空间效率.资源转化率. 2.统治者考虑问题不完全会基于老板姓利益, ...

  9. 如何用计算机把数字12变成21,2015年12月计算机二级office考试题及答案

    2015年12月计算机二级office考试题及答案 一.选择题 1.在冯·诺依曼型体系结构的计算机中引进两个重要的概念,它们是 A.引入CPU和内存储器的概念 B.采用二进制和存储程序的概念 C.机器 ...

最新文章

  1. linux关机_Linux系统管理:开机启动流程(一)
  2. python程序控制结构_python程序控制结构
  3. c语言放空一个数组,C++语言
  4. 零基础入门 Kubernetes,你需要知道这些
  5. 微博客户端播放器的演进之路
  6. php 上一页 下一页代码,php无限上一页,下一页,求完善代码??
  7. paip. uapi 过滤器的java php python 实现aop filter
  8. Java实现面向对象编程
  9. 卸载win10预装软件和小娜
  10. python反编译_反编译 python
  11. 计算机桌面壁纸在哪个文件夹,Win10桌面背景在哪个文件夹 Win10桌面背景所在文件夹介绍...
  12. php几种常用的加密解密算法
  13. 汇编语言-实验6(学习打卡Day18)
  14. python模拟登录12306_利用Python与selenium自动化模拟登陆12306官网!
  15. 常见距离算法-欧氏距离、杰卡德距离、余弦距离
  16. quartus更新symbol后没反应_Quartus II使用常见问题
  17. 计算机家庭网络未识别,Win7排除常见家庭网络问题的方法
  18. Mac怎么创建txt文件?如何设置新建txt的快捷键?
  19. 如何获取sha1值和MD5值
  20. 一键非自锁开关电路设计

热门文章

  1. Win10 docker 创建lnmp镜像
  2. HBase Configuration过程
  3. 蒙特卡洛算法计算炉石传说竞技场胜率
  4. 3D-太阳系、牧师与恶魔小游戏
  5. 面向未来的散热技术!小米自研「环形冷泵散热系统」
  6. 计算机二级操作考点,计算机二级MSOffice操作题必考点
  7. 分布式系统之Raft算法
  8. 【Paper Notes】Deep Anomaly Detection With Outlier Exposure
  9. 谷歌reCaptcha验证码服务被攻破事件回顾
  10. java-opencv剪辑图片