Codeforces 721 C. Journey (topológico de clasificación + DP)

codeforces una práctica diaria.
El significado de problemas:
Dado n puntos, m artículo borde dirigido, y el tiempo k. El tiempo de búsqueda no exceda de 1-n k puede pasar el número máximo de puntos.

ideas:

  1. Los datos <= 5000, describe un dp violenta.
  2. Puede entonces dp [i] [j] a partir de un punto de mantenimiento i a punto j ha transcurrido, entonces inicializado a INF, entonces el conjunto de dp [1] [1] = 0, 1 están hechos para asegurar que cada dp de partida.
  3. Debido a que hay, por lo que puede DP, ciclo n puntos, la complejidad sobre ^ 2 en una especie topológica cuando grafo acíclico dirigido, y para abrir un pre [i] [j] punto anterior grabado cuando, después de un punto i .
  4. Debido a abrir una serie de dos 5000 * 5000, por lo que a partir de un int, si mucho, mucho será MLE.

Código es el siguiente:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}ll Inv(ll x,ll p){return qp(x,p-2,p);}
ll Cal(ll n,ll m,ll p){if (m>n) return 0;ll ans = 1;for(int i = 1; i <= m; ++i)
ans=ans*Inv(i,p)%p*(n-i+1)%p;return ans%p;}
 
const int manx=5e3+5;
 
struct node{
    int v,next,w;
}a[manx];
queue<int>q;
int head[manx],kk=0;
int d[manx],dp[manx][manx],pre[manx][manx];
 
void add(int u,int v,int w){
    a[++kk].v=v,a[kk].w=w,a[kk].next=head[u],head[u]=kk;
}
 
int main(){
    int n=read(),m=read(),k=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read(),w=read();
        add(u,v,w);
        ++d[v];
    }
    for(int i=1;i<=n;i++)
        if(!d[i]) q.push(i);
    for(int i=1;i<=n;i++)
        for(int j=0;j<=n;j++)
            dp[i][j]=inf;
    dp[1][1]=0;
    while(q.si){
        int u=q.front(); q.pop();
        for(int x=head[u];x;x=a[x].next){
            int v=a[x].v,w=a[x].w;
            for(int i=1;i<=n;i++)
                if(dp[v][i]>dp[u][i-1]+w)
                    dp[v][i]=dp[u][i-1]+w,pre[v][i]=u;
            --d[v];
            if(!d[v]) q.push(v);
        }
    }
    int tmp=0,x=n;
    for(int i=n;i>=1;i--)
        if(dp[n][i]<=k){
            tmp=i;
            break;
        }
    printf("%d\n",tmp);
    int top=0;
    for(int i=tmp;i>=1;i--) d[++top]=n,n=pre[n][i];
    while(top) printf("%d ",d[top--]);
    return 0;
}
Publicado 83 artículos originales · ganado elogios 78 · Vistas a 30000 +

Supongo que te gusta

Origin blog.csdn.net/JiangHxin/article/details/104972585
Recomendado
Clasificación