洛谷 P3387 【模板】缩点 tarjan 虚拟头节点和虚拟尾节点

题目链接:

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

一:ac思路

参考博客:

https://www.luogu.org/blog/wyz598085788/solution-p3387

思路:

1:在用tarjan缩点时,用num[cnt]记录每一个强连通分量的值

2:核心思路:虚拟头节点f和虚拟尾节点t

3:就是经过tarjan缩点之后,把每一个强连通分量看作一个节点建图,然后把每一个强连通分量的负值当作该边的权值

4:以f为起点,t为终点跑spfa

5:用虚拟头节点f和每一个节点建一条边,权值为-num[i],每一个节点和虚拟尾节点建一条边,权值为0

 int f=0;
    int t=cnt+1;
    for(int i=1;i<=cnt;i++)
    {
        mapp[f].push_back(make_pair(i,-num[i]));
        mapp[i].push_back(make_pair(t,0));
    }
#include 

using namespace std;
const int maxn=1e4+1;
vectore[maxn];
setee[maxn];
int dfn[maxn],low[maxn],ins[maxn],color[maxn],timing,cnt,n,m,id[maxn];
int num[maxn],point[maxn];
stacks;
vector >mapp[maxn];
int d[maxn],ing[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;
            }
        }
    }
    return -d[t];
}

int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        point[i]=x;
    }
    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

二:让自己纠结多日的90分,9个测试点ac一个wa的代码

错因:

1:没有正确处理从哪一个节点开始spfa,到哪一个点的最长路径

2:一开始处理为spfa的起点为入度为零的节点,到出度为零的节点,的最长路径,然后从中取最大值

#include 

using namespace std;
const int maxn=1e4+1;
vectore[maxn];
setee[maxn];
int dfn[maxn],low[maxn],ins[maxn],color[maxn],timing,cnt,n,m,id[maxn];
int num[maxn],point[maxn];
stacks;
vector >mapp[maxn];
int d[maxn],ing[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;
            }
        }
    }
    int mi=1e9;
    for(int i=1;i<=cnt;i++)
    {
        if(ee[i].size()==0)
        {
            mi=min(d[i],mi);
        }
    }
    return -mi;
}

int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        point[i]=x;
    }
    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)