拓扑排序+DP CF721C Journey

CF721C Journey

给出一个\(n\)个点\(m\)条边的有向无环图。 问从\(1\)\(n\),在距离不超过\(k\)的情况下最多经过多少点,并输出一个方案。

\(topo\)+\(DP\).

记录路径的话,记一个前驱就行了。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int wx=5017;

inline int read(){
	int sum=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
	return sum*f;
}

int f[wx][wx],head[wx],in[wx],Ans[wx],vis[wx],h[wx],pre[wx][wx];
int n,m,k,ans,num,sum,Num;

struct e{
	int nxt,to,dis;
}edge[wx*2];

struct node{
	int nxt,to,dis;
}e[wx*2];

void Add(int from,int to,int dis){
	e[++Num].nxt=h[from];
	e[Num].to=to;
	e[Num].dis=dis;
	h[from]=Num;
}

void add(int from,int to,int dis){
	edge[++num].nxt=head[from];
	edge[num].to=to;
	edge[num].dis=dis;
	head[from]=num;
}

queue<int > q;

void dfs(int u,int tot){
	vis[u]=1;
	for(int i=h[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(vis[v])continue;
		if(f[u][tot]-e[i].dis==f[v][tot-1]){
			Ans[++sum]=v;
			dfs(v,tot-1);
		}
	}
}

int main(){
	n=read(); m=read(); k=read();
	for(int i=1;i<=m;i++){
		int x,y,z; 
		x=read(); y=read(); z=read();
		in[y]++;
		add(x,y,z); Add(y,x,z);
	}
	
	memset(f,0x3f,sizeof f);
	f[1][1]=0; for(int i=1;i<=n;i++)if(!in[i])q.push(i);
	while(q.size()){
		int u=q.front();q.pop();
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			for(int j=2;j<=n;j++){
				if(f[v][j]>f[u][j-1]+edge[i].dis){
					f[v][j]=f[u][j-1]+edge[i].dis;
					pre[v][j]=u;
				}
			} 
			in[v]--;
			if(!in[v])q.push(v);
		}
	}
	for(int i=n;i>=1;i--)if(f[n][i]<=k){ans=i;break;}
	printf("%d\n",ans); int now=n;
	if(ans){
		while(now){
			Ans[++sum]=now;
			now=pre[now][ans]; ans--;
		}
		for(int i=sum;i>=1;i--)printf("%d ",Ans[i]);
	}
	return 0;
}
posted @ 2018-11-08 06:52  _王小呆  阅读(251)  评论(0编辑  收藏  举报