问题描述

LG3119


题解

显然,如果有个环,一定是全部走完的。

所以缩点,缩出一个 \(\mathrm{DAG}\) 。

只能走一次反向,于是在正图和反图上各跑一次,枚举边,取 \(\mathrm{max}\) 即可。


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std; #define maxn 100007 template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') {
ch=getchar();fh=-1;
}
else fh=1;
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
x*=fh;
} int n,dfn[maxn],low[maxn];
int m,Head1[maxn],Next1[maxn],to1[maxn],u1[maxn],tot1;
int Head2[maxn],Next2[maxn],to2[maxn],u2[maxn],tot2;
int Head3[maxn],Next3[maxn],to3[maxn],u3[maxn],tot3;
int xx,yy;
int stac[maxn],top,ind,cnt; int sd[maxn],val[maxn];
bitset<maxn>ins;
void tarjan(int x){
dfn[x]=low[x]=++ind;stac[++top]=x;
ins[x]=1;
for(int i=Head1[x];i;i=Next1[i]){
int y=to1[i];
if(dfn[y]) {if(ins[y]) low[x]=min(low[x],dfn[y]);}
else{
tarjan(y);
low[x]=min(low[x],low[y]);
}
}
if(dfn[x]==low[x]){
cnt++;val[cnt]=1;
while(stac[top]!=x){
ins[stac[top]]=0;sd[stac[top]]=cnt;top--;++val[cnt];
}
sd[stac[top]]=cnt;top--;ins[x]=0;
}
} void add1(int x,int y){
to1[++tot1]=y,Next1[tot1]=Head1[x],Head1[x]=tot1,u1[tot1]=x;
} void add2(int x,int y){
to2[++tot2]=y,Next2[tot2]=Head2[x],Head2[x]=tot2,u2[tot2]=x;
} void add3(int x,int y){
to3[++tot3]=y,Next3[tot3]=Head3[x],Head3[x]=tot3,u3[tot3]=x;
} set <pair<int,int> > st; void rebuild(){
for(register int i=1;i<=m;i++){
// if(sd[to1[i]]==0||sd[u1[i]]==0) continue;
int x=sd[u1[i]],y=sd[to1[i]];
if(st.count(make_pair(x,y))||x==y) continue;
st.insert((make_pair(x,y)));
add2(x,y);add3(y,x);
}
} int dis[2][maxn]; void fir(){
memset(dis[0],0xcf,sizeof(dis[0]));
dis[0][sd[1]]=val[sd[1]];queue<int>q;q.push(sd[1]);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=Head2[x];i;i=Next2[i]){
int y=to2[i];
if(dis[0][y]>=dis[0][x]+val[y]) continue;
dis[0][y]=dis[0][x]+val[y];
q.push(y);
}
}
} void sec(){
memset(dis[1],0xcf,sizeof(dis[1]));
dis[1][sd[1]]=val[sd[1]];queue<int>q;q.push(sd[1]);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=Head3[x];i;i=Next3[i]){
int y=to3[i];
if(dis[1][y]>=dis[1][x]+val[y]) continue;
dis[1][y]=dis[1][x]+val[y];
q.push(y);
}
}
} int ans=0; void calc(){
for(register int i=1;i<=tot2;i++){
int x=u2[i],y=to2[i];//错误笔记:写为to2[i],开-Wall之后会有警告。
ans=max(ans,dis[0][y]+dis[1][x]);
}
printf("%d\n",ans-val[sd[1]]);//错误笔记:将sd[1]写为1,所点后1所在的结点不一定是新1号点。
} int main(){
read(n);read(m);
for(register int i=1;i<=m;i++){
read(xx);read(yy);add1(xx,yy);
}
for(register int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i); // puts("********************************");
// printf("%d\n",cnt);
// system("pause");
// puts("********************************"); rebuild();
fir();sec();
calc();
return 0;
}

LG3119 「USACO2015JAN」Grass Cownoisseur的更多相关文章

  1. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  2. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  3. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  4. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  5. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  6. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

  7. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  8. 「2014-3-17」C pointer again …

    记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...

  9. 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance

    提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...

随机推荐

  1. 【西北师大-2108Java】第五次作业成绩汇总

    [西北师大-2108Java]第五次作业成绩汇总 作业题目 面向对象程序设计(JAVA) 第7周学习指导及要求 实验目的与要求 (1)掌握四种访问权限修饰符的使用特点: (2)掌握Object类的用途 ...

  2. Web-[RoarCTF 2019]Easy Calc

    看看题目内容,一个计算器,并且过滤了非数字的值,查看源码,上了waf,并且在calc.php显示waf的规则 <?php error_reporting(0); if(!isset($_GET[ ...

  3. 【Oracle】常用的SQL语句

    抄自:https://www.cnblogs.com/qiu18359243869/p/9474515.html 提示:dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里 ...

  4. 【Excel】对比两列值

  5. SpringBootTest MockMVC绑定session(需要登陆的接口)

    https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testing spring-te ...

  6. C语言的指针用法:输入一堆字符,把非字母的删去。

    char *p,a[20]; int i; gets(a);    //这个语句不同于getchar(),后者只能一次输入一个,而前者可以一次输完所有的字符!!! p=a;        //这个语句 ...

  7. js获取url参数值的方法总结

    1.方式一:通过字符串截取的方式获取参数值: 1).函数一:获取URL中的参数名及参数值的集合 /** * [获取URL中的参数名及参数值的集合] * 示例URL:http://htmlJsTest/ ...

  8. workbook数据相关操作

    访问单个单元格 c = ws['A4'] #返回单元格A4,如果单元格不存在,则会自动创建 ws['A4'] = 4 #为单元格A4赋值为4 d = ws.cell(row=4, column=2, ...

  9. Kettle在windows上安装

    Kettle是一款国外开源的ETL工具,纯java编写,可以在Windows.Linux.Unix上运行,数据抽取高效稳定. 因为有个日常提数,工作日每天都要从数据库中提取数据,转换为excel,再以 ...

  10. go-gui-控件和信号

    go-gui-控件和信号 控件 控件简介 控件是对数据和方法的封装.控件有自己的属性和方法.属性是指控件的特征.方法是指控件的一些简单而可见的功能.如按钮就是一个控件,这个按钮是方形的,里面有张图片, ...