Portal --> bzoj2788

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\)的路径则有无数组解(因为这就说明这两个未知数之间没有约束关系)

  具体一点的话这里举个小栗子例子方便理解

  考虑这样一个“三角”不等式组:

\[\begin{cases}
B-A=c\\
C-B=a\\
C-A=b
\end{cases}
\]

  然后我们可以建出这样的一个有向图:

  然后我们考虑一下\(C-A\)的最大值,从式子来看应该是\(min(b,a+c)\),所以就是\(A\)到\(C\)的最短路,式子更多的情况也是一样的

  这里贴一个整理比较全的博(各种题目qwq):Portal

  

  然后我们回到这道题

  这题的那个式子。。长得就是差分约束系统的样子qwq,只不过我们需要稍微处理一下:

\[x+1=y\Leftrightarrow 1<=y-x<=1\Leftrightarrow x-y<=-1且y-x<=1\\
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的更多相关文章

  1. 【题解】Music Festival(树状数组优化dp)

    [题解]Music Festival(树状数组优化dp) Gym - 101908F 题意:有\(n\)种节目,每种节目有起始时间和结束时间和权值.同一时刻只能看一个节目(边界不算),在所有种类都看过 ...

  2. 【Atcoder】CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning

    [题意]给定只含小写字母的字符串,要求分割成若干段使段内字母重组顺序后能得到回文串,求最少分割段数.n<=2*10^5 [算法]DP [题解]关键在于快速判断一个字符子串是否合法,容易发现合法仅 ...

  3. 【Atcoder】CODE FESTIVAL 2017 qual A D - Four Coloring

    [题意]给定h,w,d,要求构造矩阵h*w满足任意两个曼哈顿距离为d的点都不同色,染四色. [算法]结论+矩阵变换 [题解] 曼哈顿距离是一个立着的正方形,不方便处理.d=|xi-xj|+|yi-yj ...

  4. 【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- ...

  5. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  6. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  7. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  8. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  9. 【调侃】IOC前世今生

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

随机推荐

  1. PHP核心技术——魔术方法

    魔术方法: 魔术方法是以两个下画线开头.具有特殊作用的一些方法,可以看做PHP的"语法糖". set和get方法: class Account{ private $user=1; ...

  2. CSP201609-2:火车购票

    引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...

  3. scikit-learn使用PCA降维小结

    本文在主成分分析(PCA)原理总结和用scikit-learn学习主成分分析(PCA)的内容基础上做了一些笔记和补充,强调了我认为重要的部分,其中一些细节不再赘述. Jupiter notebook版 ...

  4. I understand that you would like to know about the Amazon Giveaway

    Dear Seller, Greetings from Amazon Seller Support. From your mail, I understand that you would like ...

  5. python打印图形大全(详解)

    ,): shixin=chr() print(shixin) -------------------结果:2) for i in range(0,10): shixin=chr(9679) print ...

  6. Python中用字符串导入module

    在Python中,无法通过字符串来导入一个module文件: import "string" # Error x = "string" import x # 不 ...

  7. 树状数组怒刷sum!!!(前缀和应用)

    我们知道我们利用树状数组维护的是存到其中的a[ ]数组,但是我们做题需要的是sum[ ]数组,这才是我们真正需要的有用的信息,写这篇博客的目的便是整理一下sum数组是怎么样来应用解题的. 1. Sta ...

  8. Scrum立会报告+燃尽图(Beta阶段第二周第二次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2410 项目地址:https://coding.net/u/wuyy694 ...

  9. C++ Primer Plus学习:第十四章

    第十四章 C++中的代码重用 包含对象成员的类 将类的对象作为新类的成员.称为has-a关系.使用公有继承的时候,类可以继承接口,可能还有实现(纯虚函数不提供实现,只提供接口).使用包含时,可以获得实 ...

  10. C++ Primer Plus学习:第八章

    C++入门第八章:函数探幽 本章将介绍C++语言区别于C语言的新特性.包括内联函数.按引用传递变量.默认的参数值.函数重载以及函数模板. 1 C++内联函数 内联函数是C++为提高程序运行速度所做的一 ...