План лекций Team Master (тарджан + топологическая сортировка)

Описание темы
Чтобы принести пользу обществу, руководитель команды собирается читать лекции повсюду. В его плане n городов, может быть дорога с односторонним движением от u до v, и стоимость проезда по этой дороге равна q. Когда руководитель группы закончит свою лекцию в U City, U City направит эмиссара для прогулки вместе с ним, пока он с ним, ему нужно только заплатить 1 входную плату за город и заплатить только один раз. Плата может быть отменена. , Но посланник возвращается в ваш город, поэтому посланник будет сопровождать его только в тот город, где он сможет найти дорогу обратно в ваш город. , Мастер команды начал свои лекции в Городе № 1. Если он закончит свои лекции в Городе U, посланник доставит его в другие города в максимально возможной степени. Он надеется, что вы поможете ему найти решение, чтобы он мог учить как можно больше городов, а стоимость как можно меньше.

Введите
2 целых числа n, m в первой строке.
В следующих m строках есть 3 целых числа u, v, q в каждой строке, указывающих, что существует односторонняя дорога длиной q от u до v.

В результате получается
одна строка, два целых числа, которые являются максимальным количеством городов лекций и минимальной стоимостью.

Пример ввода
6 6
1 2 3
2 3 7
2 6 4
3 4 5
4 5 4
5 2 3

Пример вывода
6 10

Подсказка
Как показано выше, мессенджер, который ходит из 1, 2, 2 городов, доставит его в 3, 4, 5 городов, обратно в 2 города, а затем в 6, общая стоимость составит 3 + 3 + 4 = 10.
Вставьте описание изображения здесь
Для 20% данных 1 <= n <= 20,
для остальных 10% данных городская сеть представляет собой одностороннюю цепь,
для 60% данных 1 <= m <= 200000
для 100% данных, 1 < = n <= 100000
1 <= m <= 500000,1 <= q <= 1000, чтобы гарантировать отсутствие самоконтроля и двойных ребер.

Идея
запуска топологического сортировочного решения после сжатия таржана

Реализация кода

#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;
}

Опубликовано 235 оригинальных статей · Мне нравится 13 · Посещений 20 000+

рекомендация

отblog.csdn.net/weixin_43935894/article/details/105478337