Codeforces #374(Div.2)C. Journey【DAG图上的拓扑排序+Dp】

C. Journey

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Recently Irina arrived to one of the most famous cities of Berland — the Berlatov city. There aren showplaces in the city, numbered from1 ton, and some of them are connected by one-directional roads. The roads in Berlatov are designed in a way such that thereare no cyclic routes between showplaces.

Initially Irina stands at the showplace 1, and the endpoint of her journey is the showplacen. Naturally, Irina wants to visit as much showplaces as she can during her journey. However, Irina's stay in Berlatov is limited and she can't be there for more thanT time units.

Help Irina determine how many showplaces she may visit during her journey from showplace1 to showplacen within a time not exceedingT. It is guaranteed that there is at least one route from showplace1 to showplacen such that Irina will spend no more thanT time units passing it.

Input

The first line of the input contains three integersn, m andT (2 ≤ n ≤ 5000,  1 ≤ m ≤ 5000,  1 ≤ T ≤ 109) — the number of showplaces, the number of roads between them and the time of Irina's stay in Berlatov respectively.

The next m lines describes roads in Berlatov.i-th of them contains3 integersui, vi, ti (1 ≤ ui, vi ≤ n, ui ≠ vi, 1 ≤ ti ≤ 109), meaning that there is a road starting from showplace ui and leading to showplacevi, and Irina spendsti time units to pass it. It is guaranteed that the roads do not form cyclic routes.

It is guaranteed, that there is at most one road between each pair of showplaces.

Output

Print the single integer k (2 ≤ k ≤ n) — the maximum number of showplaces that Irina can visit during her journey from showplace1 to showplacen within time not exceedingT, in the first line.

Print k distinct integers in the second line — indices of showplaces that Irina will visit on her route, in the order of encountering them.

If there are multiple answers, print any of them.

Examples

Input

4 3 13
1 2 5
2 3 7
2 4 8

Output

3
1 2 4

Input

6 6 7
1 2 2
1 3 3
3 6 3
2 4 2
4 6 2
6 5 1

Output

4
1 2 4 6

Input

5 5 6
1 3 3
3 5 3
1 2 2
2 4 3
4 5 2

Output

3
1 3 5

 

题目大意:

有N个点,M条边的一个有向无环图。

让你输出一个路径,使其经过尽可能多的点,并且路径权值和小于时间限制T,路径必须保证起点为1,终点为N。


思路:


1、首先这个图是一个有向无环图(DAG图),那么其最短路可以在拓扑排序的过程中进行松弛操作,也就是说一个DAG图求最短路的时候可以不用Dij/SPFA之类的算法来做,因为其时间复杂度都比拓扑排序高。


2、想到了拓扑排序+松弛之后,然后我们想如何维护这个点的个数的问题:

我们设定一个数组dp【i】【j】,表示走到点i,经过了j个点的最短路径值。那么不难想到其状态转移方程:

dp【v】【j】=min(dp【v】【j】,dp【u】【j-1】+w(u,v));【2<=j<=n】


3、有了拓扑排序的思想,也有了dp的状态转移方程来维护一个最短路径值,那么我们敲定算法过程:

①将度为0的点全部入队列,并且初始化dp【i】【1】=0;

②每次取队头节点,对其进行拆边,并且对应每一条边,有(u,v),进行一次状态转移方程:dp【v】【j】=min(dp【v】【j】,dp【u】【j-1】+w(u,v))【2<=j<=n】

③然后再设定一个数组pre【i】【j】,和在求最短路并记录路径的方法一样,如果对应当前dp【u】【j-1】+w

④当整个拓扑排序结束之后,我们找到最大的可行解,if(dp【n】【i】<=T)anscont=i;记录下来最后一个i,就是最大的解。

⑤然后我们回溯这条路径即可。设定tmp=anscont;now=pre[now][tmp];tmp--;当now==1的时候停止即可,将答案记录在ans【】。输出即可。


4、注意数组不要开long long int 会MLE.要开int类型的数组,因为T是int范围内的,那么我们在dp过程中的时候,如果(long long int)dp【u】【j-1】+w>t ;continue即可。


Ac代码:


#include
#include
#include
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int next;
}e[60000];
int n,m,t,cont;
int dp[5002][5002];
int pre[5002][5002];
int head[5002];
int degree[5002];
int ans[5002];
void add(int from,int to,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
void top_dp()
{
    queues;
    for(int i=1;i<=n;i++)
    {
        if(degree[i]==0)
        {
            s.push(i);
            dp[i][1]=0;
        }
    }
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            for(int j=2;j<=n;j++)
            {
                long long int tmp=dp[u][j-1]+w;
                if(tmp>t)continue;
                if(dp[u][j-1]+w=0;i--)
    {
        printf("%d ",ans[i]);
    }
    printf("\n");
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        cont=0;
        memset(head,-1,sizeof(head));
        memset(degree,0,sizeof(degree));
        for(int i=0;i



你可能感兴趣的:(拓扑排序,dp)