zoukankan      html  css  js  c++  java
  • 【BZOJ4016】[FJOI2014]最短路径树问题

    【BZOJ4016】[FJOI2014]最短路径树问题

    题面

    bzoj

    洛谷

    题解

    虽然调了蛮久,但是思路还是蛮简单的2333

    把最短路径树构出来,然后点分治就好啦

    ps:如果树构萎了,这组数据可以卡掉

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <cmath>
    #include <algorithm> 
    #include <queue>
    #include <map>
    #include <vector> 
    using namespace std; 
    inline int gi() {
        register int data = 0, w = 1;
        register char ch = 0;
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar();
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
        return w * data; 
    }
    const int MAX_N = 3e4 + 5;
    const int MAX_M = 6e4 + 5;
    const int INF = 1e9; 
    int N, M, K; 
    struct Graph { int to, next, cost; } e[MAX_M << 2]; 
    int fir1[MAX_N], fir2[MAX_N], e_cnt; 
    void clearGraph() {
        memset(fir1, -1, sizeof(fir1)); 
        memset(fir2, -1, sizeof(fir2)); 
        e_cnt = 0;
    }
    void Add_Edge(int *fir, int u, int v, int w) { e[e_cnt] = (Graph){v, fir[u], w}; fir[u] = e_cnt++; } 
    vector<int> vec[MAX_N];
    bool vis[MAX_N]; 
    bool cmp(int i, int j) { return e[i].to < e[j].to; } 
    void dijkstra() { 
        static priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
        static int dis[MAX_N]; 
        fill(&dis[1], &dis[N + 1], INF);
        dis[1] = 0, que.push(make_pair(0, 1)); 
        while (!que.empty()) { 
            pair<int, int> p = que.top(); que.pop(); 
            int x = p.second; 
            if (p.first > dis[x]) continue;
    		for (int i = fir1[x]; ~i; i = e[i].next) {
    			int v = e[i].to; 
    			if (dis[v] + e[i].cost == dis[x]) vec[v].push_back(i ^ 1); 
    		} 
            for (int i = fir1[x]; ~i; i = e[i].next) {
                int v = e[i].to; 
                if (dis[x] + e[i].cost < dis[v]) { 
                    dis[v] = dis[x] + e[i].cost; 
                    que.push(make_pair(dis[v], v)); 
                } 
            } 
        } 
    } 
    void dfs(int x) { 
    	vis[x] = 1; 
    	sort(vec[x].begin(), vec[x].end(), cmp); 
    	for (int i = 0, sz = vec[x].size(); i < sz; i++) {
    		int j = vec[x][i]; if (vis[e[j].to]) continue; 
    		Add_Edge(fir2, x, e[j].to, e[j].cost), Add_Edge(fir2, e[j].to, x, e[j].cost); 
    		dfs(e[j].to); 
    	} 
    } 
    bool used[MAX_N]; 
    int size[MAX_N], dep[MAX_N], dis[MAX_N], centroid, sz, rmx, mx; 
    int stk[MAX_N], top = 0; 
    int ans1 = 0, ans2 = 0; 
    void search_centroid(int x, int fa) { 
        size[x] = 1;
        int mx = 0;
        for (int i = fir2[x]; ~i; i = e[i].next) {
            int v = e[i].to;
            if (v == fa || used[v]) continue; 
       		search_centroid(v, x);
       		size[x] += size[v];
           	mx = max(mx, size[v]); 
        }
        mx = max(mx, sz - size[x]); 
        if (mx < rmx) centroid = x, rmx = mx; 
    } 
    namespace cpp1 { 
        int bln[MAX_N]; 
        void getans(int x, int fa) {
            if (dep[x] < K - 1) ans1 = max(ans1, bln[K - 1 - dep[x]] + dis[x]); 
            for (int i = fir2[x]; ~i; i = e[i].next) { 
                int v = e[i].to; if (used[v] || v == fa) continue;
                dep[v] = dep[x] + 1; 
                dis[v] = dis[x] + e[i].cost; 
                getans(v, x); 
            } 
        } 
        void getdis(int x, int fa) { 
            stk[++top] = x; bln[dep[x]] = max(bln[dep[x]], dis[x]); 
            for (int i = fir2[x]; ~i; i = e[i].next) { 
                int v = e[i].to; if (used[v] || v == fa) continue; 
                getdis(v, x); 
            } 
        } 
        void Div(int x) { 
            used[x] = 1; top = 0; 
            for (int i = fir2[x]; ~i; i = e[i].next) {
                int v = e[i].to; if (used[v]) continue; 
                dep[v] = 1, dis[v] = e[i].cost; 
                getans(v, 0), getdis(v, 0); 
            }
            ans1 = max(ans1, bln[K - 1]); 
            for (int i = 1; i <= top; i++) bln[dep[stk[i]]] = 0; 
            for (int i = fir2[x]; ~i; i = e[i].next) { 
                int v = e[i].to; if (used[v]) continue; 
                rmx = sz = size[v], centroid = 0; 
                search_centroid(v, 0); 
                Div(centroid); 
            } 
        } 
    } 
    namespace cpp2 {
        map<pair<int, int>, int> mp; 
        void getans(int x, int fa) { 
            if (dep[x] < K - 1) ans2 += mp[make_pair(ans1 - dis[x], K - 1 - dep[x])]; 
            for (int i = fir2[x]; ~i; i = e[i].next) { 
                int v = e[i].to; if (used[v] || v == fa) continue;
                dep[v] = dep[x] + 1; 
                dis[v] = dis[x] + e[i].cost; 
                getans(v, x); 
            } 
        } 
        void getdis(int x, int fa) {
            mp[make_pair(dis[x], dep[x])]++; 
            for (int i = fir2[x]; ~i; i = e[i].next) { 
                int v = e[i].to; if (used[v] || v == fa) continue; 
                getdis(v, x); 
            } 
        } 
        void Div(int x) { 
            used[x] = 1; 
            for (int i = fir2[x]; ~i; i = e[i].next) {
                int v = e[i].to; if (used[v]) continue; 
                dep[v] = 1, dis[v] = e[i].cost; 
                getans(v, 0), getdis(v, 0); 
            } 
            ans2 += mp[make_pair(ans1, K - 1)]; 
            mp.clear(); 
            for (int i = fir2[x]; ~i; i = e[i].next) { 
                int v = e[i].to; if (used[v]) continue; 
                rmx = sz = size[v], centroid = 0; 
                search_centroid(v, 0); 
                Div(centroid); 
            } 
        }
    }
    int main () {
        N = gi(), M = gi(), K = gi(); 
        clearGraph(); 
        for (int i = 1; i <= M; i++) { 
            int u = gi(), v = gi(), w = gi();
            Add_Edge(fir1, u, v, w), Add_Edge(fir1, v, u, w); 
        } 
        dijkstra();
    	dfs(1); 
        sz = rmx = N; 
        search_centroid(1, 0); 
        cpp1::Div(centroid); 
        memset(used, 0, sizeof(used));
        sz = rmx = N, centroid = 0; 
        search_centroid(1, 0); 
        cpp2::Div(centroid); 
        printf("%d %d
    ", ans1, ans2); 
        return 0; 
    } 
    
  • 相关阅读:
    【流量劫持】SSLStrip 终极版 —— location 瞒天过海
    【流量劫持】沉默中的狂怒 —— Cookie 大喷发
    【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持
    Web 前端攻防(2014版)
    流量劫持 —— 浮层登录框的隐患
    流量劫持能有多大危害?
    流量劫持是如何产生的?
    XSS 前端防火墙 —— 整装待发
    XSS 前端防火墙 —— 天衣无缝的防护
    XSS 前端防火墙 —— 无懈可击的钩子
  • 原文地址:https://www.cnblogs.com/heyujun/p/10278244.html
Copyright © 2011-2022 走看看