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

标签: Tarjan 缩点
19人阅读 评论(0) 收藏 举报
分类:

描述

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;
}
查看评论

首届华中区程序设计邀请赛暨第十届武汉大学程序设计大赛网络预赛C题(HDOJ-4217)

这题比赛的时候是狐狸大大敲的..先用了list..结果超时了..果断树状数组A之...其实这题当年做过很类似的: POJ2828 插队排队问题..        初始所有点的值都是1..那么初始...
  • kk303
  • kk303
  • 2012-04-16 14:06:41
  • 5192

tarjan模板(缩点,求有向图强连通分量)

整理出了这个tarjan模板,具体数组的功能代码都有注释。 const int N=100010; struct data { int to,next; } tu[N*2]; int head...
  • martinue
  • martinue
  • 2016-05-04 15:53:49
  • 1693

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛

B - 合约数 思路: &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;n...
  • hnust_Derker
  • hnust_Derker
  • 2018-04-15 19:06:59
  • 123

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛F题 1+2=3?

题目链接:https://www.nowcoder.com/acm/contest/91/F题意:求第N个符合条件X^2X=3X的X。N&amp;lt;=10的12次方。解题思路:我刚开始想到最粗暴的...
  • weixin_36416680
  • weixin_36416680
  • 2018-04-16 11:01:00
  • 58

POJ 2186【Tarjan算法(模板_缩点)】

//在一张有向无环图G,图G会包含很多环(环里面的点是等价的), //当然可以把环缩成一个点(利用tarjan缩点), //形成一棵树,题目要求是求除他以外的点都指向他,也就是只有一个叶子。 //因为...
  • KEYboarderQQ
  • KEYboarderQQ
  • 2016-05-15 10:13:25
  • 1021

【牛客网】【埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛】L—K序列【动态规划】

题目链接:L—K序列题解:for一遍数组,temp[i]表示:不包括当前for到的点,序列和为i的最长长度。然后for一遍0-k,对dp[ (j+num[i])%k ]进行更新,dp[j]是包括当前点...
  • gymgym1212
  • gymgym1212
  • 2018-04-15 18:46:39
  • 170

tarjan 缩点

tarjan啊(⊙o⊙)… 嗯。。我的理解可能比较诡异先说缩点: 洛谷P3387 的模板题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求...
  • l961983207
  • l961983207
  • 2017-10-03 15:40:59
  • 112

HDU - 4607 Park Visit 求一个图中的最长链

Claire and her little friend, ykwd, are travelling in Shevchenko's Park! The park is beautiful - but...
  • tianyuhang123
  • tianyuhang123
  • 2017-05-03 16:04:48
  • 332

强连通分量及缩点tarjan算法解析

强连通分量: 简言之 就是找环(每条边只走一次,两两可达) 孤立的一个点也是一个连通分量   使用tarjan算法 在嵌套的多个环中优先得到最大环( 最小环就是每个孤立点)   定义: int Ti...
  • qq574857122
  • qq574857122
  • 2013-11-16 22:49:41
  • 11803

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛A题Wasserstein Distance

题目链接:https://www.nowcoder.com/acm/contest/91/A题意:给两组数据,求把A变成B状态需花费的最小体力。思路:s=s+abs(a[i]-b[i]);a[i+1]...
  • weixin_36416680
  • weixin_36416680
  • 2018-04-15 20:11:56
  • 36
    个人资料
    持之以恒
    等级:
    访问量: 81万+
    积分: 8892
    排名: 2701
    博客专栏
    欢迎来我的网站:www.riba2534.cn
    文章分类
    最新评论