Codeforces Round #374 (Div. 2) C. Journey DPor最短路

题意

给你一个n点m边的图,让你从1走到n,找到一条经过尽量多点的路径,且路径边权和小于等于T

然后输出路径。

分析:自己原本打算5000*5000×vector 果断爆了。。
然后用最短路的方式,dp【Node】里面记录cost和num,又在case35TLE。

  1. 看了别人,还是要好好学学记录路径的方法。。。
  2. 2.

别人的代码。。400ms
最短路spfa(一敲)220600 KB (所以其实是卡着空间过的。。把一个东西改为bool。。。

#include

using namespace std;

#define LL long long
#define MP(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define FOR(i,a,b) for(int i=a;i
#define pii pair
#define sf scanf
#define pf printf

const int maxn = 5000;

int n, m, lim;
int h[maxn+5], e[maxn+5], cost[maxn+5], nex[maxn+5];
int dis[maxn+3][maxn+3];
char inq[maxn+3][maxn+3];
int pre[maxn+3][maxn+3];
int sta[maxn+3];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int u, v, w;
    sf("%d%d%d", &n, &m, &lim);
    REP(i,1,m)
    {
        sf("%d%d%d", &u, &v, &w);
        e[i] = v, cost[i] = w, nex[i] = h[u], h[u] = i;
    }
    pii tmp, tmp2;
    int dist;
    queue que;
    mem(dis, 0x7f);
    dis[1][1] = 0, inq[1][1] = 1, pre[1][1] = 0;
    que.push( MP(1,1) );
    while(!que.empty())
    {
        tmp = que.front(); que.pop();
        inq[tmp.first][tmp.second] = 0;
        int &x = tmp.first;
        for(int i=h[x]; i; i=nex[i]) {
            tmp2.first = e[i];
            tmp2.second = tmp.second+1;
            dist = dis[x][tmp.second] + cost[i];
            if(dist > lim) continue;
            if(dist < dis[tmp2.first][tmp2.second]) {
                dis[tmp2.first][tmp2.second] = dist;
                pre[tmp2.first][tmp2.second] = x;
                if(!inq[tmp2.first][tmp2.second]) {
                    inq[tmp2.first][tmp2.second] = 1;
                    que.push(tmp2);
                }
            }
        }
    }
    int ans, now;
    for(int i=n; i>=2; --i)
        if(dis[n][i] <= lim)
        {
            pf("%d\n", ans=i);
            break;
        }
    now = n;
    while(now)
    {
        sta[++sta[0]] = now;
        now = pre[now][ans--];
    }
    for(int i=sta[0]; i>=1; --i)
    {
        if(i0]) pf(" ");
        pf("%d", sta[i]);
    }
    pf("\n");
    return 0;
}

还有。。62ms

记录后继+ dp

#include   
#define pr(x) cout << #x << "= " << x << "  " ;  
#define pl(x) cout << #x << "= " << x << endl;  
#define ll __int64  
#define mst(ss,b) memset(ss,b,sizeof(ss));  
using  namespace  std;  
const int N=5050;  
const int inf=0x3f3f3f3f;  

int n, m, T;  
int f[N][N];//f[i][j]表示当前在点i,接下来经过j个点(包括自己)到n点的最小距离  
short nxt[N][N];//nxt[i][j]表示当前在点i,接下来经过j个点(包括自己)到n点的后继  
vector< pair<int,int> >a[N];  
bool vis[N];  
void dfs(int x){  
  if (vis[x])return; vis[x] = 1;  
  for (auto it : a[x]){  
    dfs(it.first);  
    for (int i = 2; i <= n; ++i){  
      int dis = f[it.first][i - 1] + it.second;  
      if (dis < f[x][i]){  
        f[x][i] = dis;  
        nxt[x][i] = it.first;  
      }  
    }  
  }  
}  

void print(){  
  for (int i = n; ; --i)if (f[1][i] <= T){  
    printf("%d\n", i);  
    int x = 1; printf("%d ", x);  
    while (x != n){  
      x = nxt[x][i--];  
      printf("%d ", x);  
    }puts("");  
    break;  
  }  
}  

int main(){  
  while(~scanf("%d%d%d",&n, &m, &T)){  
    for (int i = 1; i <= n; ++i)a[i].clear(), vis[i] = 0;  
    for (int i = 1; i <= m; ++i){  
      int x, y, z;  
      scanf("%d%d%d", &x, &y, &z);  
      if (y == 1 || x == n)continue;  
      a[x].push_back({ y,z });  
    }  
    mst(f, inf);  
    f[n][1] = 0; vis[n] = 1;  
    dfs(1);  
    print();  
  }  
  return 0;  
}  

你可能感兴趣的:(----最短路,简单基础经典dp)