您的位置:首页 > 其它

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

2017-11-05 21:21 369 查看
题面

读清题。。。

考虑一个强联通分量,两两互相可达,那么轰炸掉这个强联通分量至少需要其中点的个数轮。

考虑一条路径,轰炸一条路径需要它的长度轮。

于是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]);
<
4000
span class="hljs-keyword">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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: