【NOIP2017提高A组冲刺11.5】轰炸

来源:互联网 发布:js input 自定义属性 编辑:程序博客网 时间:2024/04/29 09:50

Description

战狂也在玩《魔方王国》。他只会征兵而不会建城市,因此他决定对小奇的城市进行轰炸。
小奇有n 座城市,城市之间建立了m 条有向的地下通道。战狂会发起若干轮轰炸,每轮可以轰炸任意多个城市。
每座城市里都有战狂部署的间谍,在城市遭遇轰炸时,它们会通过地下通道撤离至其它城市。非常不幸的是,在地道里无法得知其它城市是否被轰炸,如果存在两个不同的城市i,j,它们在同一轮被轰炸,并且可以通过地道从城市i 到达城市j,那么城市i 的间谍可能因为撤离到城市j 而被炸死。为了避免这一情况,战狂不会在同一轮轰炸城市i 和城市j。
你需要求出战狂最少需要多少轮可以对每座城市都进行至少一次轰炸。

Input

第一行两个整数n,m。接下来m 行每行两个整数a,b 表示一条从a 连向b的单向边。

Output

输出一行仅一个整数表示答案。

Sample Input

5 4
1 2
2 3
3 1
4 5

Sample Output

3

Data Constraint

对于20%的数据,n,m<=10。
对于40%的数据,n,m<=1000。
对于另外30%的数据,保证无环。
100%的数据,n,m<=1000000。

Solution

这题拿出来愉悦大众
在往下看之前,请一定要确定你已经认真看过题
因为这题考语文


注意题面,i,j互相到达,是指他们在同一个联通块内而不是有边直接相连
这直接导致大把人爆5

那么怎么做呢?
先考虑没有环
答案显然是最长链长度
因为一条链上的点不能一起做,但层数相同不在同一条链上的点可以一起做

那么现在有环,用tarjan弄掉
由于n为10的6次房,需要人工栈或宽搜版人工栈
可以点进去看看我的模板

Code

#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define N 1010000using namespace std;int n,m,last[N],next[N*2],to[N*2],tot,bz[N],bz2[N],ans=0,zx[N],o,low[N],dfn[N],totot,p[N],zk[N],zi[N],c[N],q[N][2],r[N],num,f[N],a[N],d[N];void putin(int x,int y){    next[++tot]=last[x];last[x]=tot;to[tot]=y;}void read(int &x){    char c=getchar();x=0;    for(;c<'0'||c>'9';c=getchar());    for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;}void tarjan1(){    int x=zx[o];low[x]=dfn[x]=++tot;p[++p[0]]=x;bz[x]=bz2[x]=1;    for(int i=last[x];i;i=next[i])    {        if(!bz[to[i]])        {            zk[o]=1;zi[o]=i;zx[++o]=to[i];zk[o]=0;return;        }         else if(bz2[to[i]]) low[x]=min(low[x],dfn[to[i]]);    }    if(low[x]==dfn[x])    {        totot++;        for(;p[p[0]+1]!=x;p[0]--) c[p[p[0]]]=totot,a[totot]++,bz2[p[p[0]]]=0;    }    o--;}void tarjan2(){    int x=zx[o];low[x]=min(low[x],low[to[zi[o]]]);    for(int i=next[zi[o]];i;i=next[i])    {        if(!bz[to[i]])        {            zk[o]=1;zi[o]=i;zx[++o]=to[i];zk[o]=0;return;        }         else if(bz2[to[i]]) low[x]=min(low[x],dfn[to[i]]);    }    if(low[x]==dfn[x])    {        totot++;        for(;p[p[0]+1]!=x;p[0]--) c[p[p[0]]]=totot,a[totot]++,bz2[p[p[0]]]=0;    }    o--;}void tarjan(int x){    zx[++o]=x;zk[o]=0;zi[o]=0;    while(o>0){if(zk[o]==0) tarjan1(); else tarjan2();}}int main(){    freopen("bomb.in","r",stdin);    freopen("bomb.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,m) read(q[i][0]),read(q[i][1]),putin(q[i][0],q[i][1]);    tot=0;    fo(i,1,n) if(!bz[i]) tarjan(i);    memset(last,0,sizeof(last));num=totot;tot=0;    fo(i,1,m) if(c[q[i][0]]!=c[q[i][1]]) putin(c[q[i][0]],c[q[i][1]]),r[c[q[i][1]]]++;    int he=0,ta=0;    fo(i,1,num) if(r[i]==0) d[++ta]=i,f[i]=a[i];    while(he<ta)    {        int x=d[++he];        for(int i=last[x];i;i=next[i])        {            f[to[i]]=max(f[to[i]],f[x]+a[to[i]]);            r[to[i]]--;            if(r[to[i]]==0) d[++ta]=to[i];        }    }    fo(i,1,n) ans=max(ans,f[i]);    printf("%d\n",ans);}
阅读全文
1 0
原创粉丝点击