codeforces 721C journey(動態規劃+拓撲排序)
阿新 • • 發佈:2018-12-30
當時比賽的時候沒寫出來,然後看了網上大牛的部落格才明白的,也通過這個題明白了前向星,拓撲排序,收穫挺大的。
附上自己的程式碼,有註釋,按我自己理解寫的.
#include<bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; int n,m,t,head[5005],cnt,dp[5005][5005],pre[5005][5005],d[5005],path[5005]; //dp[i][j]表示經過j個節點(包含i點)到達i所耗費的最少時間 struct node { int to; //邊的終點 int next; //下一條相同起點的邊的序號 int w; //邊的權值 }edge[5005]; void add(int x,int y,int z) //用前向星存圖 { edge[cnt].to=y; edge[cnt].next=head[x]; edge[cnt].w=z; head[x]=cnt++; } queue<int>q; void bfs() //記憶化搜尋 { dp[1][1]=0; bool visit[5005]; for(int i=1;i<=n;i++) { if(!d[i]) { visit[i]=true; q.push(i); } } while(!q.empty()) //bfs { int top=q.front(); q.pop(); for(int i=head[top];i!=-1;i=edge[i].next) { int v=edge[i].to; if(d[v]) { d[v]--; for(int j=2;j<=n;j++) { if(dp[v][j]>dp[top][j-1]+edge[i].w) { dp[v][j]=dp[top][j-1]+edge[i].w; pre[v][j]=top; //儲存路徑,記錄與v相連的結點,即從1到v的所有結點中,第j-1個結點 } } } if(!d[v]) q.push(v); //如果d[v]為0,則以結點v為終點的邊全部遍歷完,則開始遍歷以v為起點的邊 } } } int main() { int a,b,c,max1=0,num=0,x; memset(head,-1,sizeof(head)); cnt=0; scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); d[b]++; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { dp[i][j]=INF; } } bfs(); for(int i=n;i>=1;i--) { if(dp[n][i]<=t) //尋找到達n的所有路徑中,在不超過時間t的情況下,經過結點最多的一條路徑 { max1=i; break; } } printf("%d\n",max1); x=n; while(x!=1) //儲存這條路徑 { path[++num]=x; x=pre[x][max1]; max1--; } path[++num]=1; for(int i=num;i>=1;i--) printf("%d ",path[i]); return 0; }