zoukankan      html  css  js  c++  java
  • 拓扑排序+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
    ",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;
    }
    
  • 相关阅读:
    开工--行胜于言
    操作系统之内存管理
    C陷阱与缺陷读书笔记(一)
    关于复杂度的一些基本的定义
    归并排序
    快速排序
    前序中序后序非递归遍历
    直接插入排序
    冒泡排序
    程序内存映像
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9927051.html
Copyright © 2011-2022 走看看