zoukankan      html  css  js  c++  java
  • 洛谷 p2661 信息传递(链式前向星建图)

    链式前向星

    最近看图论的板子总是有这种代码

    
    struct Edge{
        int next;   // 下一条边的下标
        int to;     // 当前边的指向
        int w;      // 当前边的权值
    };
    
    Edge edge[maxn*2];  
    int tot;        // 当前边的下标
    void addEdge(int u,int v,int w){
        edge[++tot].next = head[u];
        edge[tot].to = v;
        edge[tot].w = w;
        head[u] = tot;  // 头插法
    }
    
    

    实质就是链表的运用.
    (Edge.next)代表指向下一条边的指针,(head[u])为节点(u)的头节点,每次加入新边时用头插法.

    遍历点(u)可用

        for(int i = head[u];i;i = edge[i].next)
    

    题目: luogo P2661 信息传递

    • 题目大意: 每个点只有一个出度,求最短环(必存在)
    • 思路: (Tarjan)判环,每次跑(dfs)时将所有节点加入栈中,如果新节点已经在栈中,则存在环,从栈中找到新节点,距离栈顶的距离即为环长.
    #include<bits/stdc++.h>
    #define ll long long 
    #define FOR(i,n) for(int i =1; i <= n;++i ) 
    #define FOR0(i,n) for(int i =0; i < n;++i )  
    #define inf 0x3f3f3f3f
    #define EPS (1e-8)
    #define ALL(T)  T.begin(),T.end()
    using namespace std;
    
    const int maxn = 200010;
    int n;
    inline int input(){
        int res = 0;
        char c;
        c = getchar();
        while('0' <= c && c<='9'){
            res = res*10 + (c-'0');
            c = getchar();
        }
        return res;
    }
    
    
    struct Edge{
        int next;
        int to;
    };
    Edge edge[maxn];
    int head[maxn];
    int cnt;
    
    void addEdge(int u,int v){
        edge[++cnt].next = head[u];
        edge[cnt].to = v;
        head[u] = cnt;
    }
    int vis[maxn];
    int instack[maxn];
    stack<int> s;
    
    int ans = inf;
    bool dfs(int u){
        if(!instack[u] && !vis[u]){
            bool sign = false;
            instack[u] = 1;
            vis[u] = 1;
            s.push(u);
            for(int i=head[u];i;i=edge[i].next){
                sign |= dfs(edge[i].to);
                // if(sign)    return sign;
            }
            return sign;
        }else{ 
            if(s.empty()){  return false;}
            int to = s.top();
            int idx = 0;
            while(to!=u){
                s.pop();
                idx++;
                if(s.empty()){
                    return false;
                }
                to = s.top();
            }
            ans = min(ans,idx+1);
            return true;
        }
    }
    int main(){
        n = input();
        int to;
        FOR(i,n){
            to = input();
            addEdge(i,to);
        }
        FOR(i,n){
            if(!vis[i]){
                dfs(i);
                while(!s.empty())   s.pop();
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    所有节点只被访问一次即可每次memset(vis)结果TLE了QAQ,其实这道题还有更简单的写法,不过纯属练手了.

    题目
    前向星博客

  • 相关阅读:
    SharePoint Workflow出了问题, 除了ULS log还可以看什么日志?
    Kernel Mode Debugging 初步 一
    一些debug常用的"魔法"数值
    SQL Block的初级排查
    [持续更新]一些有用的PowerShell收集
    关于斜杠(slash)和反斜杠(back slash)的小知识点
    如何安全地解放C盘剩余磁盘空间?
    返璞归真asp.net mvc 1.0(3) Controller/Action【转】
    关于Oxite的教训
    [翻译ASP.NET MVC]Contact Manager开发之旅之迭代2 修改样式,美化应用 【转】
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11234272.html
Copyright © 2011-2022 走看看