The 16th Wuhan University Programming Contest (Online Contest) FA-maze-ing (Tarjan, shorten the point, find the longest chain)

describe

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

ideas

This question gives na point and man edge, which is a directed graph. Let you find a longest chain, so that the chain has the most points, and find the number of points.

Because it may form a ring, we use tarjanthe shrinking operation to shrink the points of the same set into one point, and then create a new graph to record the number of points in each strongly connected component.

Finally, use BFSit to find the longest path. The method is to find the point with an in-degree of 0, and then traverse the graph to find the maximum value.

code

#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;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324487914&siteId=291194637