【bzoj2788】Festival
Description
有\(n\)个正整数\(X_1,X_2,...,X_n\),再给出\(m1+m2\)个限制条件,限制分为两类:
1、给出\(a,b (1<=a,b<=n)\),要求满足\(X_a + 1 = X_b\)
2、 给出\(c,d (1<=c,d<=n)\),要求满足\(X_c <= X_d\)
在满足所有限制的条件下,求集合\(\{X_i\}\)大小的最大值,如果无解输出"NIE"
数据范围$2<=n<=600, 1<=m1+m2<=100,000 $
Solution
同样也是。。借这题补个档:差分约束系统
差分约束系统的话是将形如\(x_i-x_j<=a\)这样的式子转化成有向图中的一条\(j\rightarrow i\)长度为\(a\)的边,然后对于一个不等式组,我们可以用这样的方式建一个有向图出来,不等式组中未知数\(x_j-x_i\)的最大值即为\(x_i\)到\(x_j\)的最短路径长度,如果说有向图中存在负环那么就是无解的情况,如果说不存在\(x_i\)到\(x_j\)的路径则有无数组解(因为这就说明这两个未知数之间没有约束关系)
具体一点的话这里举个小栗子例子方便理解
考虑这样一个“三角”不等式组:
B-A=c\\
C-B=a\\
C-A=b
\end{cases}
\]
然后我们可以建出这样的一个有向图:
然后我们考虑一下\(C-A\)的最大值,从式子来看应该是\(min(b,a+c)\),所以就是\(A\)到\(C\)的最短路,式子更多的情况也是一样的
这里贴一个整理比较全的博(各种题目qwq):Portal
然后我们回到这道题
这题的那个式子。。长得就是差分约束系统的样子qwq,只不过我们需要稍微处理一下:
x<=y\Leftrightarrow x-y<=0\\
\]
然后建出有向图,然后我们通过负环就可以直接判掉无解的情况了
接下来只考虑有解的情况
为了方便思考我们先假装已经缩好了点,每个点代表一个强联通分量
这时这个新图里面一定没有环了,并且由于我们的建图方式,所以我们可以肯定缩完点之后的图中所有的边权都是\(0\),否则一定会有一条反向的边,那就与缩完点的性质矛盾了(这个性质十分关键)
我们可以发现,由于题目要求的是集合大小,也就是不同的元素个数,如果两个点不在同一个强联通分量里面,那么这两个点的取值一定能构造出一种答案使得两个点的取值不同,再推广一下,我们会发现其实两个强联通分量对答案的贡献是不会相互影响的,也就是说我们只需要将每个强联通分量的答案算出来然后最后求和就可以得到最后的答案了
现在的问题是怎么求一个强联通分量内部的答案
我们挑一个强联通分量进行考虑,如果说我们挑的这个强联通分量中差值最大的两个数\(x_1,x_2\),假设他们的最大差值(也就是最短路)为\(a\)
考虑一下这个有向图的特殊性质:边权\(\in \{-1,0,1\}\),并且因为这个图除去强联通分量外不存在环了,所以强联通分量中的两个点之间的最短路一定走的是强联通分量中的边,所以如果说最大差值为\(a\)(也就是最短路长度为\(a\)),这条路径一定是由若干条\(0\),若干条\(1\),若干条\(-1\)的边构成的,而那就说明增大只能\(+1\)这样来增大,所以中间包含的所有的数一定都能被取到,也就是说有\(a+1\)个不同的数
所以一个强联通分量对答案的贡献就是\(a+1\)了,然后这题就十分愉快滴做完啦
一个小trick:因为这题的点数很少,所以我们可以直接用Floyd来求最短路(反正你查询的时候。。每个点出发的最短路都要查。。),判负环的话直接跑完Floyd之后看一下是否存在一个\(i\)满足\(dis[i][i]<0\)就好了
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=610,M=100010,inf=2147483647;
int dis[N][N],mp[N][N];
int h[N],dfn[N],low[N],st[N],inst[N],pre[N],mx[N];
int id[N];
int n,m1,m2,dfn_t,top,ans,cnt;
void tarjan(int x){
dfn[x]=low[x]=++dfn_t; inst[x]=1; st[++top]=x;
for (int i=1;i<=n;++i){
if (i==x||!mp[x][i]) continue;
if (!dfn[i]){
tarjan(i);
low[x]=min(low[i],low[x]);
}
else if (inst[i]){
low[x]=min(low[x],dfn[i]);
}
}
int u;
if (low[x]==dfn[x]){
++cnt; u=st[top];
while (u!=x){
id[u]=cnt;
inst[u]=false;
u=st[--top];
}
id[x]=cnt;
inst[u]=false;
--top;
}
}
int floyd(){
for (int k=1;k<=n;++k)
for (int i=1;i<=n;++i){
if (dis[i][k]==inf) continue;
for (int j=1;j<=n;++j){
if (dis[k][j]==inf) continue;
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
void add(int x,int y,int d){
dis[x][y]=min(dis[x][y],d);
mp[x][y]=true;
}
void solve(){
dfn_t=0; top=0;
for (int i=1;i<=n;++i)
if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
if (i==j||id[i]!=id[j]) continue;
mx[id[i]]=max(mx[id[i]],dis[i][j]);
}
ans=0;
for (int i=1;i<=cnt;++i)
ans+=mx[i]+1;
printf("%d\n",ans);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y;
scanf("%d%d%d",&n,&m1,&m2);
memset(mp,false,sizeof(mp));
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
dis[i][j]=inf;
for (int i=1;i<=m1;++i){
scanf("%d%d",&x,&y);
add(x,y,1);//1<=y-x<=1
add(y,x,-1);
}
for (int i=1;i<=m2;++i){
scanf("%d%d",&x,&y);
add(y,x,0);//x-y<=0
}
floyd();
bool flag=true;
for (int i=1;i<=n&&flag;++i)
if (dis[i][i]<0) flag=false;
if (!flag){printf("NIE\n");return 0;}
solve();
}
【bzoj2788】Festival的更多相关文章
- 【题解】Music Festival(树状数组优化dp)
[题解]Music Festival(树状数组优化dp) Gym - 101908F 题意:有\(n\)种节目,每种节目有起始时间和结束时间和权值.同一时刻只能看一个节目(边界不算),在所有种类都看过 ...
- 【Atcoder】CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning
[题意]给定只含小写字母的字符串,要求分割成若干段使段内字母重组顺序后能得到回文串,求最少分割段数.n<=2*10^5 [算法]DP [题解]关键在于快速判断一个字符子串是否合法,容易发现合法仅 ...
- 【Atcoder】CODE FESTIVAL 2017 qual A D - Four Coloring
[题意]给定h,w,d,要求构造矩阵h*w满足任意两个曼哈顿距离为d的点都不同色,染四色. [算法]结论+矩阵变换 [题解] 曼哈顿距离是一个立着的正方形,不方便处理.d=|xi-xj|+|yi-yj ...
- 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA
1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【调侃】IOC前世今生
前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...
随机推荐
- VirtualBox虚拟机上安装windows7系统
1.下载Windows7的镜像文件 http://www.xitongcheng.com/jiaocheng/win7_article_24156.html 2.在虚拟机上安装Windows7 htt ...
- Ubuntu 安装python后,安装python-dev
1.通常情况下: sudo apt install python-dev 或者 在 sudo apt install python 命令下安装应该也附带了 python-dev 上述 pyhthon ...
- [C++]boost dijkstra获得两点间的最短路
需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...
- Lua学习笔记(7): 模块
模块 模块就像是c语言工程项目目录里的.h.c文件或外部依赖项,为某一个文件的代码提供依赖,其实就是把工作分成几个模块,方便项目的管理,提高开发效率和维护效率 在Lua中,模块其实就是一个表,实现方式 ...
- MapReduce和yarn
1.Mapreduce是什么? Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架: Mapreduce核心功能是将用户编写的业务逻辑代码和自带默 ...
- 【python 3.6】python获取当前时间及过去或将来的指定时间
最近有个查询api,入参需要一个startTime,一个endTime,刚好用到datetime. 留此记录. #python 3.6 #!/usr/bin/env python # -*- codi ...
- PHP性能优化 -实战篇
借助xhprof 工具分析PHP性能 XHPorf(源自Fackbook 的PHP性能分析工具) 实战 通过分析Wordpress程序,做优化! 优化 找到需要优化的函数 grep 'impo ...
- UI优秀框架(库)
1.vux 官网:https://doc.vux.li/zh-CN/ Github:https://github.com/airyland/vux 13818 Stars 3064 Forks ...
- mysql数据库查询
查询数据指从数据库中获取所需要的数据.查询数据是数据库操作中最常用,也是最重要的操作.用户可以根据自己对数据的需求,使用不同的查询方式.通过不同的查询方式,可以获得不同的数据.MySQL中是使用SEL ...
- Yii2 配置request组件解析 json数据
在基础版本的config目录下 web.php 或者高级版config目录下的main.php中配置 'components' =>[ 'request' => [ 'parsers' = ...