题意

有 \(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的更多相关文章

  1. [BZOJ2788][Poi2012]Festival

    2788: [Poi2012]Festival Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 187  Solved: 91[Submit][Statu ...

  2. 【bzoj2788】Festival

    Portal --> bzoj2788 Description 有\(n\)个正整数\(X_1,X_2,...,X_n\),再给出\(m1+m2\)个限制条件,限制分为两类: 1.给出\(a,b ...

  3. 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 ...

  4. hdu 1850 Being a Good Boy in Spring Festival(Nimm Game)

    题意:Nimm Game 思路:Nimm Game #include<iostream> #include<stdio.h> using namespace std; int ...

  5. UVALive 7281 Saint John Festival (凸包+O(logn)判断点在凸多边形内)

    Saint John Festival 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/J Description Porto's ...

  6. 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 ...

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

  8. 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 ...

  9. 「AtCoder Grand018B」Sports Festival(暴力)

    题目链接B - Sports Festival 题意 n(1~300)个人m(1~300)个活动,\(A_{ij}\)表示i第j喜欢的活动,每个人选择在举办的活动里最喜欢的,因此可以通过选择一些活动来 ...

  10. 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 ...

随机推荐

  1. 20155323 2016-2017-2 《Java程序设计》第4周学习总结

    20155323 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 继承的目的:继承是为了多态,能够采用父类引用指向子类对象,这样可以让代码更灵活.继承之后可以 ...

  2. 20155325 2016-2017-2 《Java程序设计》第2周学习总结

    教材学习内容总结 上节课讲了些思维方法:git,vim的使用技巧,推荐了picpick截图软件. 第三章书本上涵盖了基本语法内容 由于在语法方面java和c有相似之处,所以我重点关注不同之处和易忽略之 ...

  3. WPF DataGridTable

    由于项目要显示表头合并,而数据源列随时变更,又不想重复的画表格,就实现动态数据(dynamic)绑定和配置数据列模板的方式 编辑DataGridColumnHeader样式实现表头合并:效果如下 实现 ...

  4. linux下汇编语言开发总结

    汇编语言是直接对应系统指令集的低级语言,在语言越来越抽象的今天,汇编语言并不像高级语言那样使用广泛,仅仅在驱动程序,嵌入式系统等对性能要求苛刻的领域才能见到它们的身影.但是这并不表示汇编语言就已经没有 ...

  5. mnist手写数字识别(神经网络)

    import numpy as np from sklearn.neural_network import MLPClassifier path = 'mnist.npz' f = np.load(p ...

  6. 如何使用Win+R快捷键打开自定义程序

    鉴于大家对于提高效率这块有争议,更改了下标题. 大家平时一定都使用过Win+R运行快捷键, 在运行里可以快捷的打开一些系统软件,比如说输入mstsc是打开远程连接,输入explorer是打开文件管理器 ...

  7. 1.5 JAVA的高并发编程

    一.多线程的基本知识 1.1进程与线程的介绍(上个博客1.4中已经详细介绍进程和线程) 程序运行时在内存中分配自己独立的运行空间,就是进程 线程:它是位于进程中,负责当前进程中的某个具备独立运行资格的 ...

  8. Hive中使用sql的注意事项

    一.别名的使用 定义别名:columnA as X 不需要使用单引号 使用别名:不与where同时使用 花式报错-->有说hive不支持where后使用别名 二.GROUP BY select ...

  9. Python中如何实现im2col和col2im函数(sliding类型)

    今天来说说im2col和col2im函数,这是MATLAB中两个内置函数,经常用于数字图像处理中.其中im2col函数在<MATLAB中的im2col函数>一文中已经进行了简单的介绍. 一 ...

  10. Java Monitoring&Troubleshooting Tools

    JDK Tools and Utilities Monitoring Tools You can use the following tools to monitor JVM performance ...