拓撲排序+DP CF721C Journey
阿新 • • 發佈:2018-11-08
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; }