• 洛谷 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,其实这道题还有更简单的写法,不过纯属练手了.

    题目
    前向星博客

  • 相关阅读:
    Ubuntu16.04更新源后apt-get update报错的解决方法
    安装Ubuntu16.04 64bit系统时出错的解决方案
    采用Python-Qt5制作置顶透明桌面提醒词/座右铭/便签
    如何手动解析Keras等框架保存的HDF5格式的权重文件
    读取yml配置文件中的值
    添加20位随机数,不重复,可以用来作为发票申请流水等功能
    java 从json串中取出某个字段的值
    Spring事务的两种方式
    (附表设计)超级全面的权限系统设计方案
    nfs 测试
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11234272.html
Copyright © 2020-2023  润新知