BZOJ1297: [SCOI2009]迷路

看上去有点据称的意思,感觉这边权不太会搞啊

发现边权范围∈[1, 9]

其实可以拆点,一个点拆成九个点

一条从 i 到 j 的长为 k 路径就是从 i 的第 k 个点连向 j 的第一个点

答案就是 1 的第一个点到 n 的第一个点的方案数

矩乘一波就好了


代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cctype>
#include<queue>
using namespace std;
  
const int MAXN = 500005;
  
struct EDGE{
    int nxt, to, val;
    EDGE(int NXT = 0, int TO = 0, int VAL = 0) {nxt = NXT; to = TO; val = VAL;}
}edge[MAXN << 1];
int n, s, totedge, mxpt, p, q, top, lmt, ans = 0x7fffffff;
int head[MAXN], dst[MAXN], frm[MAXN];
pair<int,int> stk[MAXN];
bool ind[MAXN];
queue<int> que;
  
inline int rd() {
    register int x = 0;
    register char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)) {
        x = x * 10 + (c ^ 48);
        c = getchar();
    }
    return x;
}
inline void add(int x, int y, int v) {
    edge[++totedge] = EDGE(head[x], y, v);
    head[x] = totedge;
    return;
}
inline void bfs(int bgn) {
    for(int i = 1; i <= n; ++i) dst[i] = 0x7fffffff;
    dst[bgn] = 0;
    que.push(bgn);
    while(!que.empty()) {
        int x = que.front(); que.pop(); if(dst[x] > dst[mxpt]) mxpt = x;
        for(int i = head[x]; i; i = edge[i].nxt) if(dst[edge[i].to] == 0x7fffffff) {
            int y = edge[i].to;
            frm[y] = x;
            if(ind[y]) dst[y] = dst[x];
            else dst[y] = dst[x] + edge[i].val;
            que.push(y);
        }
    }
    return;
}
void dfs(int x, int fa) {
    dst[x] = 0;
    for(int i = head[x]; i; i = edge[i].nxt) if(edge[i].to != fa) {
        int y = edge[i].to;
        dfs(y, x);
        if(ind[y]) dst[x] = max(dst[x], dst[y]);
        else dst[x] = max(dst[x], dst[y] + edge[i].val);
    }
    return;
}
  
int main() {
    n = rd(); s = rd();
    register int xx, yy, vv;
    for(int i = 1; i < n; ++i) {
        xx = rd(); yy = rd(); vv = rd();
        add(xx, yy, vv); add(yy, xx, vv);
    }
    bfs(1); p = mxpt; mxpt = 0;
    bfs(p); q = mxpt;
    stk[++top] = make_pair(mxpt, dst[mxpt]); ind[mxpt] = true;
    while(mxpt != p) {
        mxpt = frm[mxpt];
        stk[++top] = make_pair(mxpt, dst[mxpt]);
        ind[mxpt] = true;
    }
    dfs(p, 0);
    for(int i = 1; i <= top; ++i) lmt = max(lmt, dst[stk[i].first]);
    int lptr, rptr = 0, cur;
    for(lptr = 1; lptr <= top; ++lptr) {
        cur = lmt;
        while(stk[lptr].second - stk[rptr + 1].second <= s && rptr + 1 <= top) ++rptr;
        cur = max(cur, max(stk[1].second - stk[lptr].second, stk[rptr].second));
        ans = min(ans, cur);
    }
    printf("%d\n", ans);
    return 0;
}

  

 

posted @ 2018-09-04 14:55  EvalonXing  阅读(150)  评论(0编辑  收藏  举报