武汉大学第十六届程序设计大赛(网络赛) F.A-maze-ing(Tarjan,缩点,求最长链)

版权声明:欢迎转载~转载请注明出处! https://blog.csdn.net/riba2534/article/details/79966220

描述

Long long age, a wise but barbaric king made a plan to convert the
arena to a maze so that he could get pleasure from watching his
servant running the maze confusedly. The structure of the arena could
be abstracted into a directed connected graph comprised of n (1 ≤ n ≤
105 ) nodes and m (1 ≤ m ≤ 2 × 105 ) edges. The king had not decided
where to set up the starting nodes and the end node. So the king
proposed a requirement. Whichever two points u, v he chose, there
existed a path from one point to the other(a path from u to v or from
v to u). Moreover, the king hoped to improve the difficulty of the
game, so the number of nodes in the maze should be as large as
possible. You are only required to output the maximum number of nodes
in the maze.

Input

There are two positive integers n and m in the first line. And then m
lines follow, in each line there are two positive integers u and v,
describing that an edge from node u to node v.

Output

Just output one integer, the maximum size of the maze

Sample Input

3 2
1 2
1 3

Sample Output

2

思路

本题给了n个点和m条边,是一个有向图。让你找出一个最长链,使得这条链上的点最多,求点的个数。

因为可能成环,所以我们利用tarjan进行缩点操作,把同一个集合的点都缩成一个点,然后建立新的图,记录每个强连通分量中的点的个数。

最后利用BFS来求出最长路,方法就是找出入度为0的点,然后遍历这个图找出最大值就行

代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int N=1e5+10;
const int M=2e5+10;
int dfn[N],low[N],vis[N],color[N],cnt,times;
int in[N],depth[N];
int num[N];//缩点后点的数量
int first[N],tot;
stack<int>s;
vector<int>dag[N];
struct edge
{
    int v,next;
} e[M];
void add_edge(int u,int v)
{
    e[tot].v=v;
    e[tot].next=first[u];
    first[u]=tot++;
}
void init()
{
    mem(dfn,0);
    mem(low,0);
    mem(vis,0);
    mem(num,0);
    mem(depth,0);
    mem(color,0);
    mem(in,0);
    mem(first,-1);
    cnt=0;
    times=0;
    tot=0;
    while(!s.empty())s.pop();
}
void tarjan(int u)
{
    vis[u]=1;
    s.push(u);
    dfn[u]=low[u]=++times;
    for(int i=first[u]; ~i; i=e[i].next)
    {
        int v=e[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        cnt++;
        while(1)
        {
            int now=s.top();
            s.pop();
            num[cnt]++;
            color[now]=cnt;
            vis[now]=0;
            if(now==u)break;
        }
    }
}
void bfs()
{
    queue<int>q;
    for(int i=1; i<=cnt; i++)
        if(!in[i])//从入度为0的点搜索
        {
            q.push(i);
            depth[i]=num[i];
        }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(auto v:dag[u])
        {
            in[v]--;
            depth[v]=max(depth[v],depth[u]+num[v]);
            if(!in[v]) q.push(v);
        }
    }
    int ans=0;
    for(int u=1; u<=cnt; u++)
        ans=max(ans,depth[u]);
    printf("%d\n",ans);
}

int main()
{
    int n,m,u,v;
    scanf("%d%d",&n,&m);
    init();
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&u,&v);
        add_edge(u,v);
    }
    for(int i=1; i<=n; i++)
        if(!dfn[i])
            tarjan(i);
    for(u=1; u<=n; u++)
        for(int i=first[u]; ~i; i=e[i].next)
        {
            v=e[i].v;
            if(color[u]!=color[v])
            {
                dag[color[u]].push_back(color[v]);//缩点后建立新图
                in[color[v]]++;//计算v的入度
            }
        }
    bfs();
    return 0;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页