Team Master's lecture plan (tarjan + topological sorting)

Topic description
In order to benefit the society, the team master is going to give lectures everywhere. There are n cities in his plan, there may be a one-way road from u to v, and the cost of passing this road is q. When the team leader finished his lecture in U City, U City will send an emissary to walk with him. As long as the emissary is with him, he only needs to pay 1 entrance fee for the city and only needs to pay once. The fee can be waived. . But the messenger is going back to u city, so the messenger will only accompany him to the city where he can find the way back to u city. . Team Master started his lectures in City No. 1. If he finished his lectures in City U, the messenger would take him to other cities as much as possible. He hopes that you will help him find a solution so that he can teach as many cities as possible, and the cost is as small as possible.

Enter
2 integers n, m in the first line.
In the next m rows, there are 3 integers u, v, q in each row, indicating that there is a one-way road of length q from u to v.

The output is
one line, two integers, which are the maximum number of lecture cities and the minimum cost.

Sample input
6 6
1 2 3
2 3 7
2 6 4
3 4 5
4 5 4
5 2 3

Sample output
6 10

Tip
As shown above, the messenger who walks from 1 to 2, 2 cities will take him to 3, 4, 5 cities, back to 2 cities, and then to 6, the total cost is 3 + 3 + 4 = 10.
Insert picture description here
For 20% of the data, 1 <= n <= 20;
for the other 10% of the data, the urban network is a one-way chain;
for 60% of the data, 1 <= m <= 200000
for 100% of the data, 1 < = n <= 100000
1 <= m <= 500000,1 <= q <= 1000, to ensure that there is no self-loop and no double edges.

The idea
of running topological sorting solution after shrinking tarjan

Code

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=500005;
const int M=500005;
const int INF=0x3f3f3f3f;
const ll LINF=1e18;
const ull sed=31;
const ll mod=998244353;
const double eps=1e-7;
const double PI=3.14159265358979;
typedef pair<int,int>P;
typedef pair<double,double>Pd;

struct node
{
    int to,index,w;
}E[M];
int eu[M],ev[M],ew[M];
int n,m,cnt,head[N];
int Stack[N],dfn[N],low[N],tot,dep,top;
int ltp[N],ltps[N];
int deg[N],num[N],val[N];
bool viss[N];
queue<int>q;

void add(int u,int v,int w)
{
    E[++cnt].to=v;
    E[cnt].index=head[u];
    E[cnt].w=w;
    head[u]=cnt;
}

void tarjan(int u)
{
    dfn[u]=low[u]=++dep;
    Stack[++top]=u;
    viss[u]=true;
    for(int i=head[u];i;i=E[i].index)
    {
        if(!dfn[E[i].to])
        {
            tarjan(E[i].to);
            low[u]=min(low[u],low[E[i].to]);
        }
        else if(viss[E[i].to]) low[u]=min(low[u],dfn[E[i].to]);
    }
    if(dfn[u]==low[u])
    {
        ++tot;
        int v;
        do
        {
            v=Stack[top--];
            viss[v]=false;
            ltp[v]=tot;
            ++ltps[tot];
        }while(u!=v);
    }
}

void dfs(int u)
{
    for(int i=head[u];i;i=E[i].index)
        if(++deg[E[i].to]==1) dfs(E[i].to);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&eu[i],&ev[i],&ew[i]);
        add(eu[i],ev[i],ew[i]);
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    memset(head,0,sizeof(head));
    cnt=0;
    for(int i=0;i<m;i++)
        if(ltp[eu[i]]!=ltp[ev[i]])
            add(ltp[eu[i]],ltp[ev[i]],ew[i]);
    dfs(ltp[1]);
    memset(val,0x3f,sizeof(val));
    num[ltp[1]]=val[ltp[1]]=ltps[ltp[1]];
    val[ltp[1]]--;
    q.push(ltp[1]);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=E[i].index)
        {
            int v=E[i].to;
            deg[v]--;
            if(deg[v]==0) q.push(v);
            if(num[v]<num[u]+ltps[v])
            {
                num[v]=num[u]+ltps[v];
                val[v]=val[u]+E[i].w+ltps[v]-1;
            }
            else if(num[v]==num[u]+ltps[v]) 
                val[v]=min(val[v],val[u]+E[i].w+ltps[v]-1);
        }
    }
    int ans=0;
    for(int i=1;i<=cnt;i++)
    {
        if(num[ans]<num[i]) ans=i;
        else if(num[i]==num[ans] && val[i]<val[ans]) ans=i;
    }
    printf("%d %d\n",num[ans],val[ans]);
    return 0;
}

Published 235 original articles · Like 13 · Visits 20,000+

Guess you like

Origin blog.csdn.net/weixin_43935894/article/details/105478337