• 图的遍历


    图的遍历

    时空限制1000ms / 128MB

    题目描述

    给出N个点,M条边的有向图,对于每个点v,求A(v)表示从点v出发,能到达的编号最大的点。

    输入输出格式

    输入格式:

    第1 行,2 个整数N,M。

    接下来M行,每行2个整数Ui,Vi,表示边(Ui,Vi)。点用1,2,,N编号。

    输出格式:

    N 个整数A(1),A(2),,A(N)。

    输入输出样例

    输入样例: 
    4 3
    1 2
    2 4
    4 3
    输出样例: 
    4 4 3 4

    说明

    • 对于60% 的数据,1N,K≤10^3

    • 对于100% 的数据,1N,M≤10^5


    一开始以为是道dfs水题,结果忘了有环。。。。。。。最后写了个tarjan缩点加dfs。

    然后看了一下他们的题解,发现可以反向建边,然后按编号从大到小dfs。。。。。。。。

    #include<bits/stdc++.h>
    #define N 100050
    using namespace std;
    
    struct ss
    {
        int to,next;
    };
    
    ss edg[N];
    int head[N];
    int now_edge=0;
    
    void addedge(int u,int v)
    {
        edg[now_edge]=(ss){v,head[u]};
        head[u]=now_edge++;
    }
    
    
    int dfn[N],low[N],color[N],now_clock,now_color;
    int Stack[N],top;
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++now_clock;
        Stack[top++]=x;
        
        for(int i=head[x];i!=-1;i=edg[i].next)
        {
            int v=edg[i].to;
            if(!dfn[v])
            {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else
            if(!color[v])low[x]=min(low[x],dfn[v]);
        }
        
        if(low[x]==dfn[x])
        {
        //    for(int i=1;i<=4;i++)printf("%d ",color[i]);
        //    printf("
    ");
            now_color++;
            while(Stack[top-1]!=x)
            {
                color[Stack[--top]]=now_color;
            }
            color[Stack[--top]]=now_color;
        }
    }
    
    int ans[N];
    int max_point[N]={0};
    
    int dfs(int x)
    {
    //    printf("%d
    ",x);
        if(ans[x])return ans[x];
        int Max=max_point[x];
        for(int i=head[x];i!=-1;i=edg[i].next)
        Max=max(Max,dfs(edg[i].to));
        
        return ans[x]=Max;
    }
    
    void init()
    {
        memset(ans,0,sizeof(ans));
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(color,0,sizeof(color));
        now_edge=0;
        top=1;
        now_color=0;
        now_clock=1;
    }
    int a[N],b[N];
    
    int main()
    {
        int n,m;
        scanf("%d %d",&n,&m);
        init();
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d",&a[i],&b[i]);
            addedge(a[i],b[i]);
        }
    
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        
        memset(head,-1,sizeof(head));
        now_edge=0;
        
    //    for(int i=1;i<=n;i++)printf("%d ",color[i]);
        
        for(int i=1;i<=m;i++)
        {
            if(color[a[i]]!=color[b[i]])addedge(color[a[i]],color[b[i]]);
        }
        
        for(int i=1;i<=n;i++)max_point[color[i]]=max(max_point[color[i]],i);
        
        for(int i=1;i<=n;i++)printf("%d%c",dfs(color[i]),i==n?'
    ':' ');
        return 0;
    }
    View Code(tarjan+dfs)
  • 相关阅读:
    给a标签加样式的写法
    IE6、IE7下不支持overflowy:hidden;
    fontfamily:微软雅黑
    文字加下划线
    IE8下按钮与右边的距离比IE7和IE6的多了一倍
    在button(div)里设置背景图后,在IE6下背景图的高度被撑开了
    li中包含span,在IE6、IE7下会有3pxbug
    事件冒泡
    [LeetCode] Insert Interval 解题报告
    [LeetCode] Generate Parentheses 解题报告
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9671236.html
Copyright © 2020-2023  润新知