Codeforces#374(div2)- C. Journey(二分答案+dp)

来源:互联网 发布:淘宝网安卓版电脑下载 编辑:程序博客网 时间:2024/05/19 14:53

题目链接

http://codeforces.com/contest/721/problem/C

思路

二分最多能够经过多少个点,然后dp判断
状态表示
d[i][j]:当前在第i个点,经过了j个点的最小距离
转移方程
d[i][j]=min(d[k][j1]+w(i,k),d[i][j]) (k是i的前驱,w(k, i)表示k到i的边长)
边界条件
当i == 1时,只要j1即可,即走到起点的时候,实际经过的点的数目可以不到j

细节

  1. 二分的时候L = 1,如果L = 2的话不会进入dp,因此不会记录路径
  2. 记录路径的时候也需要开2维
  3. 建图的时候边要反向,因为找的是前驱

代码

#include <iostream>#include <cstring>#include <stack>#include <vector>#include <set>#include <map>#include <cmath>#include <queue>#include <sstream>#include <iomanip>#include <fstream>#include <cstdio>#include <cstdlib>#include <climits>#include <deque>#include <bitset>#include <algorithm>using namespace std;#define PI acos(-1.0)#define LL long long#define PII pair<int, int>#define PLL pair<LL, LL>#define mp make_pair#define IN freopen("in.txt", "r", stdin)#define OUT freopen("out.txt", "wb", stdout)#define scan(x) scanf("%d", &x)#define scan2(x, y) scanf("%d%d", &x, &y)#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)#define sqr(x) (x) * (x)const int maxn = 5000 + 5;const int INF = 0x3e3e3e3e;struct Edge {    int from, to, dist;    Edge(int u, int v, int w) : from(u), to(v), dist(w) {    }};vector<Edge> edges;vector<int> G[maxn];int n, m, T;void addedge(int u, int v, int w) {    edges.push_back(Edge(u, v, w));    G[u].push_back(edges.size() - 1);}int d[maxn][maxn], pa[maxn][maxn];int dp(int i, int j) {    if (d[i][j] != -1) return d[i][j];    if (i == 1) return d[i][j] = j <= 1 ? 0 : INF;    d[i][j] = INF;    for (int ii = 0; ii < G[i].size(); ii++) {        Edge e = edges[G[i][ii]];        int k = e.to;        int t = dp(k, j - 1) + e.dist;        if (t < d[i][j]) {            d[i][j] = t;            pa[i][j] = k;        }    }    return d[i][j];}bool judge(int x) {    memset(d, -1, sizeof(d));    int t = dp(n, x);    return t <= T;}void print(int u, int x) {    if (u == 1) return;    print(pa[u][x], x - 1);    printf(" %d", u);}int main() {    scan3(n, m, T);     for (int i = 0; i < m; i++) {        int x, y, z;        scan3(x, y, z);        addedge(y, x, z);    }    int L = 1, R = n, M = (L + R) >> 1;    while (L < R) {        if (R == L + 1) {            if (judge(R)) M = R;            else {                judge(L);                M = L;            }            break;        } else {            M = (L + R) >> 1;            if (judge(M)) L = M;            else R = M;        }    }    printf("%d\n", M);    printf("1");    print(n, M);    return 0;}
0 0
原创粉丝点击