CF131D Subway 题解

· · 题解

题目传送门

前置知识

强连通分量 | 最短路

解法

考虑用 Tarjan 进行缩点,然后跑最短路。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define sort stable_sort 
#define endl '\n'
struct node
{
    int nxt,to,w;
}e[10000];
int head[10000],u[10000],v[10000],dfn[10000],low[10000],ins[10000],c[10000],dis[10000],vis[10000],cnt=0,tot=0,ans=0,scc=0,rt=0;
stack<int>s;
void add(int u,int v)
{
    cnt++;
    e[cnt].nxt=head[u];
    e[cnt].to=v;
    e[cnt].w=1;
    head[u]=cnt;
}
void tarjan(int x,int fa)
{
    int i,k=0;
    tot++;
    dfn[x]=low[x]=tot;
    ins[x]=1;
    s.push(x);
    for(i=head[x];i!=0;i=e[i].nxt)
    {
        if(e[i].to!=fa)
        {
            if(dfn[e[i].to]==0)
            {
                tarjan(e[i].to,x);
                low[x]=min(low[x],low[e[i].to]);
            }
            else
            {
                if(ins[e[i].to]==1)
                {
                    low[x]=min(low[x],dfn[e[i].to]);
                }
            }
        }
    }
    if(dfn[x]==low[x])
    {
        ans++;
        scc=0;
        while(x!=k)
        {
            k=s.top();
            ins[k]=0;
            c[k]=ans;
            scc++;
            s.pop();
        }
        if(scc>=2)
        {
            rt=ans;
        }
    }
}
void dijkstra(int s)
{
    int x,i;
    priority_queue<pair<int,int> >q;
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;
    q.push(make_pair(0,-s));
    while(q.empty()==0)
    {
        x=-q.top().second;
        q.pop();
        if(vis[x]==0)
        {
            vis[x]=1;
            for(i=head[x];i!=0;i=e[i].nxt)
            {
                if(dis[e[i].to]>dis[x]+e[i].w)
                {
                    dis[e[i].to]=dis[x]+e[i].w;
                    q.push(make_pair(-dis[e[i].to],-e[i].to));
                }
            }
        }
    }
}
int main()
{
    int n,i;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>u[i]>>v[i];
        add(u[i],v[i]);
        add(v[i],u[i]);
    }
    for(i=1;i<=n;i++)
    {
        if(dfn[i]==0)
        {
            tarjan(i,0);
        }
    }
    cnt=0;
    memset(e,0,sizeof(e));
    memset(head,0,sizeof(head));
    for(i=1;i<=n;i++)
    {
        if(c[u[i]]!=c[v[i]])
        {
            add(c[u[i]],c[v[i]]);
            add(c[v[i]],c[u[i]]);
        }
    }
    dijkstra(rt);
    for(i=1;i<=n;i++)
    {
        cout<<dis[c[i]]<<" ";
    }
    return 0;
}    

后记

推销一下自己的 Tarjan 学习笔记 。