[2017纪中11-5]轰炸 强联通分量+DAG最长路

来源:互联网 发布:剑灵正太捏脸数据 编辑:程序博客网 时间:2024/09/21 08:55

题面
读清题。。。
考虑一个强联通分量,两两互相可达,那么轰炸掉这个强联通分量至少需要其中点的个数轮。
考虑一条路径,轰炸一条路径需要它的长度轮。
于是tarjan缩点在拓扑排序一下跑一个DAG最长路即可。
代码:

#include<iostream>#include<cstdio>using namespace std;const int maxn=1000010;int n,m,tim,nc,top,ans,st[maxn],dfn[maxn],low[maxn],col[maxn],sz[maxn],rd[maxn],len[maxn],ord[maxn];bool vis[maxn],vst[maxn];struct edge{    int t;    edge *next;}*con[maxn],*sd[maxn];void ins(int x,int y){    edge *p=new edge;    p->t=y;    p->next=con[x];    con[x]=p;}void ins2(int x,int y){    edge *p=new edge;    p->t=y;    p->next=sd[x];    sd[x]=p;}void tarjan(int v){    dfn[v]=low[v]=++tim;    vst[v]=vis[v]=1;    st[++top]=v;    for(edge *p=con[v];p;p=p->next)        if(!vis[p->t]) tarjan(p->t),low[v]=min(low[v],low[p->t]);        else if(vst[p->t]) low[v]=min(low[v],dfn[p->t]);    if(low[v]==dfn[v])    {        nc++;        while(st[top+1]!=v)        {            vst[st[top]]=0;            col[st[top--]]=nc;            sz[nc]++;        }    }}void suodian(){    for(int i=1;i<=n;i++)        for(edge *p=con[i];p;p=p->next)            if(col[i]!=col[p->t]) {ins2(col[i],col[p->t]);rd[col[p->t]]++;}}void tuopu(){    top=0;    for(int i=1;i<=nc;i++)        if(rd[i]==0)st[++top]=i;    int pnt=0;    while(top>0)    {        ord[++pnt]=st[top--];        for(edge *p=sd[ord[pnt]];p;p=p->next)        {            rd[p->t]--;            if(rd[p->t]==0) st[++top]=p->t;        }    }    for(int i=nc;i>=1;i--)    {        for(edge *p=sd[ord[i]];p;p=p->next)            len[ord[i]]=max(len[ord[i]],len[p->t]);        len[ord[i]]+=sz[ord[i]];        }}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int x,y;        scanf("%d%d",&x,&y);        ins(x,y);    }    for(int i=1;i<=n;i++)        if(!vis[i]) tarjan(i);    ans=0;    suodian();    tuopu();        for(int i=1;i<=nc;i++)        ans=max(ans,len[i]);    printf("%d",ans);               return 0;}
原创粉丝点击