CodeForces 721C
問題描述:CodeForces 721C
思路:這是一個拓撲圖,詢問從1到n在T時間內最多能觀光幾個景點,並輸出順序,有邊權。
這題是一個拓撲dp,考慮dp[i][j],到達i點時,觀光了j個景點的最小時間
轉移是這樣對於一條邊u -> v,dp[v][j] = min(dp[v][j],dp[u][j - 1] + dis[u][v]);
當時不會儲存多個點的情況,用dp儲存即可。
AC程式碼:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <math.h>
#include <string.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
const int maxn=5005;
const int inf=0x3f3f3f3f;
//int dis[maxn][maxn];
int vin[maxn];
struct edge
{
int v;
int cost;
edge(int a,int b)
{
v=a,cost=b;
}
};
typedef vector<edge> vec;
vec e[maxn];
int n,m,t;
struct node
{
int per;
int use;
} dp[maxn][maxn];
void tp()
{
queue<int>q;
for(int i=1; i<=n; i++)
if(vin[i]==0)
q.push(i);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0; i<e[u].size(); i++)
{
int v=e[u][i].v;
int cost=e[u][i].cost;
vin[v]--;
if(vin[v]==0)
q.push(v);
for(int j=1; j<=n; j++)
if(dp[v][j].use>dp[u][j-1].use+cost)
{
dp[v][j].use=dp[u][j-1].use+cost;
dp[v][j].per=u;
}
}
}
}
void show(int i,int j)
{
if(dp[i][j].per==-1)
{
printf("1 ");
return;
}
show(dp[i][j].per,j-1);
printf("%d ",i);
}
int main()
{
//freopen("intput.txt","r",stdin);
cin>>n>>m>>t;
int a,b,c;
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
{
dp[i][j].use=inf;
}
memset(vin,0,sizeof(vin));
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
e[a].push_back(edge(b,c));
vin[b]++;
}
//fill(tp,tp+maxn*maxn-1,inf);
dp[1][1].use=0;
dp[1][1].per=-1;
tp();
//for(int i=0;i<k;i++)cout<<topu[i]<<' ';
//cout<<endl;
for(int i=n; i>=1; i--)
{
if(dp[n][i].use<=t)
{
printf("%d\n",i);
show(n,i);
return 0;
}
}
return 0;
}