bzoj2788-Festival
题意
有 \(n\) 个变量,有两种限制,分别有 \(m_1,m_2\) 种。限制如下:
- \(a_x+1=a_y\)
- \(a_x\le a_y\)
求 \(\{x_i\}\) 集合的大小。\(n\le 600,m_1+m_2\le 10^5\) 。
分析
求集合大小其实就是最多有多少个变量不相同。看到这种变量的加减约束问题,首先想到了差分约束。
建边,若 \(a_x+1=a_y\) ,那么 \(a_x+1\ge a_y,a_y-1\ge a_x\) ,所以连边 \((x,y,1),(y,x,-1)\) 。
若 \(a_x\le a_y\) 那么连边 \((y,x,0)\) 。
先考虑一些特殊的情况。若出现非0的环,就说明出现了矛盾,排除掉这种情况。
对这个图缩环,那么形成了一个DAG,其中的边权值都为0,否则一定有一条跟它反向的边,那么就出现了一个新的环,与DAG定义不符。
那么每一个新点所代表的不同强连通分量之间的点的取值是不影响的。我们只需要考虑每一个的最多取值,全部加起来即可,因为总可以构造出不冲突的方案。
在一个强连通块中走出一条路径,就对应着一组可能的解。从第一个点开始标号,经过边权为1就加一,经过边权为-1就减一,经过边权为0就不变,这样我们得到的解一定是合法的,因为我们满足了所有的要求,而且我们已经排除了正权回路,即不会出现任何矛盾。同时我们得到的解一定是这条路径上从小到大标号中最优的,因为标号必定是连续的。同时,所有的解都能够在图上找到一条路径与之对应。
若这条路径的开头或结尾是-1,那么我们去掉这个,答案变优了,称这个操作为一次优化,那么对于一条路径,不断地优化,然后除去开头就是\((1,-1)\) 和结尾为 \((-1,1)\) 的,这样答案要么变优,要么不变。
最终我们得到了一条路径,这条路径是某两个点间的最短路,它的权值最大。这个权值的意义其实是终点减去起点的值的最大值。由于边权只有 \(\{-1,0,1\}\) ,所以每一个都会被取到。
综上,一个强连通块中的最多取值就是最短路中最长的+1 。
代码
发现之前的Tarjan写的不太对,ins[x] 数组应该在弹栈的时候标记为 false ,而不是退出dfs的时候。
#include<bits/stdc++.h>
using namespace std;
inline char nchar() {
static const int bufl=1<<20;
static char buf[bufl],*a,*b;
return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
}
inline int read() {
int x=0,f=1;
char c=nchar();
for (;!isdigit(c);c=nchar()) if (c=='-') f=-1;
for (;isdigit(c);c=nchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=605;
int n,d[maxn][maxn],col[maxn],cs=0,inf,ans[maxn];
int dfn[maxn],low[maxn],sta[maxn],top=0,dfx=0;
bool ins[maxn],mp[maxn][maxn];
inline void Max(int &x,int y) {x=max(x,y);}
inline void Min(int &x,int y) {x=min(x,y);}
void tarjan(int x) {
dfn[x]=low[x]=++dfx;
sta[++top]=x;
ins[x]=true;
for (int i=1;i<=n;++i) if (i!=x && mp[x][i]) {
if (!dfn[i]) tarjan(i),Min(low[x],low[i]); else
if (ins[i]) Min(low[x],dfn[i]);
}
if (dfn[x]==low[x]) {
++cs;
int v;
do col[v=sta[top--]]=cs,ins[v]=false; while (v!=x);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read();
memset(d,0x3f,sizeof d);
inf=d[0][0];
for (int i=1;i<=n;++i) d[i][i]=0;
int m1=read(),m2=read();
while (m1--) {
int x=read(),y=read();
Min(d[x][y],1);
Min(d[y][x],-1);
mp[x][y]=mp[y][x]=true;
}
while (m2--) {
int x=read(),y=read();
Min(d[y][x],0);
mp[y][x]=true;
}
for (int k=1;k<=n;++k) for (int i=1;i<=n;++i) if (d[i][k]!=inf) for (int j=1;j<=n;++j) if (d[k][j]!=inf) Min(d[i][j],d[i][k]+d[k][j]);
for (int i=1;i<=n;++i) if (d[i][i]<0) puts("NIE"),exit(0);
for (int i=1;i<=n;++i) if (!dfn[i]) tarjan(i);
fill(ans+1,ans+cs+1,1);
for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) if (i!=j && col[i]==col[j]) Max(ans[col[i]],d[i][j]+1);
printf("%d\n",accumulate(ans+1,ans+cs+1,0));
return 0;
}
bzoj2788-Festival的更多相关文章
- [BZOJ2788][Poi2012]Festival
2788: [Poi2012]Festival Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 187 Solved: 91[Submit][Statu ...
- 【bzoj2788】Festival
Portal --> bzoj2788 Description 有\(n\)个正整数\(X_1,X_2,...,X_n\),再给出\(m1+m2\)个限制条件,限制分为两类: 1.给出\(a,b ...
- HDU1850 Being a Good Boy in Spring Festival(博弈)
Being a Good Boy in Spring Festival Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I ...
- hdu 1850 Being a Good Boy in Spring Festival(Nimm Game)
题意:Nimm Game 思路:Nimm Game #include<iostream> #include<stdio.h> using namespace std; int ...
- UVALive 7281 Saint John Festival (凸包+O(logn)判断点在凸多边形内)
Saint John Festival 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/J Description Porto's ...
- reading words in your computer and changing to female voice, linux festival text2wave saving wav files
on a brand new linux PC, e.g. ubuntu 14.04 amd64 To hear voice sudo apt-get install festival -y then ...
- Being a Good Boy in Spring Festival(尼姆博弈)
Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 ...
- Being a Good Boy in Spring Festival(杭电1850)(尼姆博弈)
Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32 ...
- 「AtCoder Grand018B」Sports Festival(暴力)
题目链接B - Sports Festival 题意 n(1~300)个人m(1~300)个活动,\(A_{ij}\)表示i第j喜欢的活动,每个人选择在举办的活动里最喜欢的,因此可以通过选择一些活动来 ...
- HDU 1850 Being a Good Boy in Spring Festival (Nim博弈)
Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32 ...
随机推荐
- 单线程的redis为什么吞吐量可以这么大
原文:单线程的redis为什么吞吐量可以这么大 一.Redis的高并发和快速原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.r ...
- 【MongoDB安装】MongoDB在centos linux平台安装
参考:http://www.runoob.com/mongodb/mongodb-linux-install.html 一..下载安装包 下载方式: 1.登录官网download,然后通过xftp传到 ...
- OpenCL入门:(三:GPU内存结构和性能优化)
如果我们需要优化kernel程序,我们必须知道一些GPU的底层知识,本文简单介绍一下GPU内存相关和线程调度知识,并且用一个小示例演示如何简单根据内存结构优化. 一.GPU总线寻址和合并内存访问 假设 ...
- Python range() 函数用法
函数语法 range(start, stop[, step]) 参数说明: start: 计数从 start 开始.默认是从 0 开始.例如range(5)等价于range(0, 5); stop: ...
- kubeadm构建k8s之Prometheus-operated监控(0.18.1)
介绍: 大家好,k8s的搭建有许多方式,也有许多快速部署的,为了简化部署的复杂度,官方也提供了开源的kubeadm快速部署,最新1.10.x版本已经可以实现部署集群, 如果你对k8s的原理已经非常了解 ...
- [ Continuously Update ] This is an *Index Page*.
The links below present papers in certain fields. Despite overlaps exist, their emphasis is markedly ...
- C++进阶训练——停车收费系统设计
一.简介 经过一段时间的c++基础学习,是时候做一个较为全面的.运用c++功能的较复杂的项目练练手了. 运用软件:Visual Studio (VS). 题目:c++停车收费系统设计(某本编程书进 ...
- IC设计前后端流程与EDA工具
IC前端设计(逻辑设计)和后端设计(物理设计)的区分: 以设计是否与工艺有关来区分二者:从设计程度上来讲,前端设计的结果就是得到了芯片的门级网表电路. 前端设计的流程及使用的EDA工具 1.架构的设计 ...
- 《C》VS控制台应用
源(c)文件:主要是源码,包括程序入口,函数的实现 头(h)文件:主要是定义的函数声明 资源(rc)文件:程序中用到的辅助资源,比如位图,图标资源 解决VS2015安装后stdio.h ucrtd.l ...
- Python:字符串操作总结
所有标准的序列操作(索引.分片.乘法.判断成员资格.求长度.取最小值最大值)对字符串同样适用,且字符串是不可变的. 一.字符串格式化 转换说明符 [注]: 这些项的顺序至关重要 (1)%字符:标记转换 ...