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

题目
前向星博客

原文地址:https://www.cnblogs.com/xxrlz/p/11234272.html