Codeforces 721 C.旅(トポロジー的ソート+ DP)

毎日の練習をcodeforces。
問題の意味:
n個の点が与えられると、m個の物品有向エッジ、およびk個の時間。1-nを超える点の最大数を渡すことができkのない時間を求めています。

アイデア:

  1. データ<= 5000は、暴力的なDPを説明しました。
  2. 次いで、点jにiが経過したメンテナンス点から[I] [j]をDPができ、次いで、INFに初期化し、その後、セットDP [1] [1] = 0、1が各出発DPことを確認するために行われます。
  3. あるので、私たちはDP、サイクルn点、非環式有向グラフ、および[I] [j]を記録前のポイントを事前を開くために、トポロジカルソートにおける^ 2上の複雑さを可能な場合、点Iの後。
  4. そうMLE場合、長い長い、int型になり始め、* 5000 2 5000の配列をオープンする予定。

コードは以下の通りであります:

#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;
}
公開された83元の記事 ウォン称賛78 ビュー30000 +

おすすめ

転載: blog.csdn.net/JiangHxin/article/details/104972585