• 【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; 
    } 
    
  • 相关阅读:
    反编译DLL文件
    tr设置display属性时,在FF中td合并在第一个td中显示的问题
    sqlserver 服务器主体 无法在当前安全上下文下访问数据库
    BootStrap glyphicons字体图标
    SignalR 2.0入门
    Asp.net SignalR 实现服务端消息推送到Web端
    车牌,车架号,VIN码毫秒识别技术,汽车后市场的春天到来了
    车架号VIN码识别,合格证,购车发票,房产证,车牌,驾驶证,行驶证,征信报告等等识别 从易鑫、大搜车、淘车网,看汽车金融发展新模式
    车架号识别,VIN码识别 助力汽车后市场
    译图智讯VIN码识别助力汽配商转型升级
  • 原文地址:https://www.cnblogs.com/heyujun/p/10278244.html
Copyright © 2020-2023  润新知