洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur tarjan缩点 spfa 双向建图跑spfa

题目链接:

https://www.luogu.org/problem/P3119

参考博客:

https://wangym.blog.luogu.org/solution-p3119

建议再次细读一下这一个博客

思路:

1:tarjan缩点

2:建图,把缩点之后的每一个强连通分量看作一个节点

      1:建一个正向图,然后从color[1]跑spfa,那么就得到了,从color[1]到各点的最短路径(取负即为最长路径)

      2:建一个反向图,然后从color[1]跑spfa,那么就得到了,各点到color[1]的最短路径(取负即为最长路径)

      3:边的权值为边的终点的节点所包含的原始图的节点个数,即,这一个强连通分量的-colornum值

3: 在正向图中假如点i有一条指向点t的边,那么在i->t的路径上逆行,将经过(-d[t]-d2[i]+colornum[color[1]]) 个草场。所以很容易求得,ans=max(-d[t]-d2[i]+colornum[color[1]],ans);

一:最简代码

#include 

using namespace std;
const int maxn=1e5+1;
vectore[maxn];
setee[maxn];
int dfn[maxn],low[maxn],ins[maxn],color[maxn],timing,cnt,n,m;
int colornum[maxn];
stacks;
vector >mapp[maxn],mapp2[maxn];
int d[maxn],ing[maxn],d2[maxn],ing2[maxn];

void tarjan(int x)
{
    low[x]=dfn[x]=++timing;
    s.push(x);
    ins[x]=1;
    for(int i=0;i >*mapp,int *d,int *ing)
{
    queueq;
    q.push(x);
    d[x]=0;
    ing[x]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        ing[now]=0;
        for(int i=0;id[now]+mapp[now][i].second)
            {
                d[v]=d[now]+mapp[now][i].second;
                if(ing[v])
                    continue;
                q.push(v);
                ing[v]=1;
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        cin>>a>>b;
        e[a].push_back(b);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            tarjan(i);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j

二:写两次spfa的代码(没有将spfa设置参数,使代码有重复,这种写法不好)

#include 

using namespace std;
const int maxn=1e5+1;
vectore[maxn];
setee[maxn];
int dfn[maxn],low[maxn],ins[maxn],color[maxn],timing,cnt,n,m;
int colornum[maxn];
stacks;
vector >mapp[maxn],mapp2[maxn];
int d[maxn],ing[maxn],d2[maxn],ing2[maxn];

void tarjan(int x)
{
    low[x]=dfn[x]=++timing;
    s.push(x);
    ins[x]=1;
    for(int i=0;iq;
    q.push(x);
    d[x]=0;
    ing[x]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        ing[now]=0;
        for(int i=0;id[now]+mapp[now][i].second)
            {
                d[v]=d[now]+mapp[now][i].second;
                if(ing[v])
                    continue;
                q.push(v);
                ing[v]=1;
            }
        }
    }
}

void spfa2(int x)
{
    queueq;
    q.push(x);
    d2[x]=0;
    ing2[x]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        ing2[now]=0;
        for(int i=0;id2[now]+mapp2[now][i].second)
            {
                d2[v]=d2[now]+mapp2[now][i].second;
                if(ing2[v])
                    continue;
                q.push(v);
                ing2[v]=1;
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        cin>>a>>b;
        e[a].push_back(b);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            tarjan(i);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j

 

 

 

 

你可能感兴趣的:(tarjan加spfa)