51nod 2842 城际旅行

原题链接

image

这题因为要求满足 t 时间内,所以用 dp ,不过我们的状态比较特殊,\(dp[i][j]\) 表示到 \(i\) 点时经过 \(j\) 个点的最短时间,因为题目为 DAG 所以要用拓扑排序,每到一个点,枚举所有出边,更新出点的状态 \(f[v][j+1]=min(f[v][j+1],f[u][j])\),最后的答案就是所有 \(f[t][j]\le t\) 中最大的 \(j\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 5005

int n,m;
ll t;
int cnt=0;
struct Edge{
	int to,next,w;
}edge[2*N];
int head[N];

void add_edge(int u,int v,int w){
	cnt++;
	edge[cnt].to=v;
	edge[cnt].next=head[u];
	edge[cnt].w=w;
	head[u]=cnt;
} 

int in[N];
queue<int> q;
ll f[N][N];


void topo_sort(){
	
	for(int i=1;i<=n;i++){
		if(!in[i]){
			q.push(i);
		}
	}
	
	while(!q.empty()){
		int x=q.front();
		q.pop();
		
		for(int i=head[x];i!=-1;i=edge[i].next){
			int y=edge[i].to;
			
			for(int j=1;j<=n;j++){
				ll kk=f[x][j]+edge[i].w;
				if(kk<=t){//直接不加超过t的,其实加也行
					f[y][j+1]=min(f[y][j+1],kk);
				}
			}
			
			if(--in[y]==0){
				q.push(y);
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m>>t;
	
	for(int i=1;i<=n;i++){
		head[i]=-1;
	} 
	
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add_edge(u,v,w);
		in[v]++;
	}
	
	memset(f,0x3f,sizeof f);
	
	f[1][1]=0; 
	
	topo_sort();

	for(int j=n;j>=1;j--){
		if(f[n][j]<=t){
			cout<<j;
			return 0;
		}
	} 
	cout<<0;
	return 0; 
}
posted @ 2024-09-04 10:34  sad_lin  阅读(4)  评论(0编辑  收藏  举报