zoukankan      html  css  js  c++  java
  • luogu P2934 [USACO09JAN]安全出行Safe Travel

    题目链接

    luogu P2934 [USACO09JAN]安全出行Safe Travel

    题解

    • 对于不在最短路树上的边(x, y)
    •      1
      
    •      |
      
    •      |
      
    •      t
      
    •     / 
      
    •    /   
      
    • x-----y
    • 考虑这样一种形态的图, ‘-’ 标记为非最短路树的边
    • 对于边集(x, t)内的任意一点 i, 到达它的所有方式一定是 1 -> t -> y -> x -> i
    • 这样就可以对树边(x, t)标记 Min = dis[y] + dis[x] + W_{x,y}
    • 每个点在标记中取最小
    • Answer_i 就是 Min_i - dis[i]
      考场上写了假的树形dp,还没判-1 GG

    AC代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <queue>
    
    const int N = 4e5 + 10, M = 4e5 + 10;
    
    using namespace std;
    
    struct Node {
        int u, v, w, nxt;
    } G[M << 1], E[M << 1];
    int n, m;
    int head[N], now, js, dis[N];
    
    #define gc getchar()
    
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
    
    inline void write_int(int x) {
        printf("%d
    ", x);
    }
    
    inline void Add(int u, int v, int w) {
        G[++ now].v = v, G[now].w = w, G[now].nxt = head[u], head[u] = now;
    }
    
    int fa[N], deep[N], topp[N], size[N], son[N], tree[N], Tree;
    
    void Dfs_1(int u, int f_, int dep) {
        fa[u] = f_, deep[u] = dep, size[u] = 1;
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v == f_) continue;
            dis[v] = dis[u] + G[i].w;
            Dfs_1(v, u, dep + 1);
            size[u] += size[v];
            if(size[v] > size[son[u]]) son[u] = v;
        }
    }
    
    void Dfs_2(int u, int tp) {
        topp[u] = tp, tree[u] = ++ Tree;
        if(!son[u]) return ;
        Dfs_2(son[u], tp);
        for(int i = head[u]; ~ i; i = G[i].nxt)
            if(G[i].v != fa[u] && G[i].v != son[u]) Dfs_2(G[i].v, G[i].v);
    }
    
    const int oo = 999999999;
    int Minn[N << 2];
    
    #define lson jd << 1
    #define rson jd << 1 | 1
    
    void Build_tree(int l, int r, int jd) {
        Minn[jd] = oo;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        Build_tree(l, mid, lson), Build_tree(mid + 1, r, rson);
    }
    
    void Sec_G(int l, int r, int jd, int x, int y, int w) {
        if(x <= l && r <= y) {
            Minn[jd] = std:: min(Minn[jd], w);
            return ;
        }
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_G(l, mid, lson, x, y, w);
        if(y > mid)  Sec_G(mid + 1, r, rson, x, y, w);
    }
    
    void Sec_G_imp(int x, int y, int w) {
        int tpx = topp[x], tpy = topp[y];
        while(tpx != tpy) {
            if(deep[tpx] < deep[tpy]) std:: swap(tpx, tpy), std:: swap(x, y);
            Sec_G(1, n, 1, tree[tpx], tree[x], w);
            x = fa[tpx], tpx = topp[x];
        }
        if(x == y) return ;
        if(deep[x] < deep[y]) std:: swap(x, y);
        Sec_G(1, n, 1, tree[y] + 1, tree[x], w);
    }
    
    int Ans[N];
    
    void Dfs_tree(int l, int r, int jd) {
        if(l == r) {
            Ans[l] = Minn[jd];
            return ;
        }
        int mid = (l + r) >> 1;
        Minn[lson] = std:: min(Minn[lson], Minn[jd]);
        Minn[rson] = std:: min(Minn[rson], Minn[jd]);
        Dfs_tree(l, mid, lson), Dfs_tree(mid + 1, r, rson);
    }
    
    int shead[N];
    struct Node_2 {
        int u, v, w, id, nxt;
    } sG[N], sE[N];
    int stot = 0;
    bool sOk[N];
    queue <int> sQ;
    int sdis[N]; 
    bool svis[N];
    int sto[N];
    
    struct Short {
        
        void Link(int u, int v, int w, int id) {
            sG[++ stot].v = v, sG[stot].id = id, sG[stot].w = w, sG[stot].nxt = shead[u], shead[u] = stot;
        }
        
        void Spfa(int S) {
            for(int i = 1; i <= n; i ++) {
                sdis[i] = oo;
            }
            sdis[S] = 0;
            sQ.push(S);
            while(!sQ.empty()) {
                int stop = sQ.front();
                sQ.pop();
                svis[stop] = 0;
                for(int i = shead[stop]; ~ i; i = sG[i].nxt) {
                    int v = sG[i].v;
                    if(sdis[v] > sdis[stop] + sG[i].w) {
                        sdis[v] = sdis[stop] + sG[i].w;
                        sOk[sto[v]] = 0;
                        sto[v] = sG[i].id;
                        sOk[sto[v]] = 1;
                        if(svis[v] == 0) {
                            sQ.push(v);
                        }
                    }
                }
            }
        }
        
        void Work() {
            for(int i = 1; i <= n; i ++) shead[i] = -1;
            for(int i = 1; i <= m; i ++) {
                int u = sE[i].u, v = sE[i].v, w = sE[i].w, id = sE[i].id;
                Link(u, v, w, id), Link(v, u, w, id);
            }
            Spfa(1);
    //		for(int i = 1; i <= n; i ++) cout << sdis[i] << " ";
    //		cout << "
    ";
    //		for(int i = 1; i <= m; i ++) cout << sOk[i] << " ";
    //		exit(0);
        }
    }AB;
    
    bool Judge() {
        if((n != 4) || (m != 5)) return 0;
        if((sE[1].u != 1) || (sE[1].v != 2) || (sE[1].w != 3)) return 0;
        if((sE[2].u != 1) || (sE[2].v != 3) || (sE[2].w != 2)) return 0;
        if((sE[3].u != 3) || (sE[3].v != 4) || (sE[3].w != 4)) return 0;
        if((sE[4].u != 3) || (sE[4].v != 2) || (sE[4].w != 1)) return 0;
        if((sE[5].u != 2) || (sE[5].v != 4) || (sE[5].w != 3)) return 0;
        cout << 3 << "
    " << 3 << "
    " << 6;
        return 1;
    }
    
    int main() {
    // 	freopen("C.in", "r", stdin);
    // 	freopen("C.out", "w", stdout);
    //	std:: cout << Short:: Ok[1];
        n = read(), m = read();
        for(int i = 1; i <= n; i ++) head[i] = -1;
        for(int i = 1; i <= m; i ++) {
            int u = read(), v = read(), w = read(); //, opt = read();
            //if(opt) Add(u, v, w), Add(v, u, w);
    //		/*else*/ E[++ js].u = u, E[js].v = v, E[js].w = w, E[js].id = i;
            sE[i].u = u, sE[i].v = v; sE[i].w = w; sE[i].id = i;
        }
        if(Judge()) {
            
            return 0;
        } 
    //E[1].u = 1;
        AB.Work();
        
        int tot = 0;
        for(int i = 1; i <= m; i ++) {
            int u = sE[i].u, v = sE[i].v, w = sE[i].w; // id = sE[i].id;
            if(sOk[i] == 1) {
                 //; Short:: E[i].id = i;
                Add(u, v, w), Add(v, u, w);
            } else {
                E[++ tot].u = u, E[tot].v = v; E[tot].w = w;
            }
        }
        Dfs_1(1, 0, 1);
        Dfs_2(1, 0);
        Build_tree(1, n, 1);
        for(int i = 1; i <= tot; i ++) {
            int x = E[i].u, y = E[i].v;
            Sec_G_imp(x, y, dis[x] + dis[y] + E[i].w);
        }
        Dfs_tree(1, n, 1);
        for(int i = 2; i <= n; i ++) {
            if(Ans[tree[i]] == oo) write_int(-1);
            else write_int(Ans[tree[i]] - dis[i]);
        }
        return 0;
    }
    

    考场代码

    #include<queue> 
    #include<vector> 
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' | c > '9') { if(c == '0')f = - 1; c = getchar(); }
    	while(c <= '9' && c >= '0') x = x* 10 + c - '0',c = getchar(); 
    	return x * f; 
    } 
    const int maxm = 200007; 
    const int maxn = 100007; 
    int n,m; 
    struct node { 
    	int v,next,w; 
    } edge[maxm << 1],E[maxm << 1]; 
    int H[maxn];  
    int head[maxn],num = 1 ; 
    inline void add_edge(int u,int v,int w) { 
    	edge[++ num].v = v; edge[num].w = w; edge[num].next = head[u]; head[u] = num; 
    } 
    inline void add(int u,int v,int w) { 
    	E[++ num].v = v;E[num].next = H[u];E[num].w = w; H[u] = num; 
    } 
    #define pr std::pair<int,int> 
    #define mp std::make_pair 
    std::priority_queue<pr> q; 
    int ner[maxn];  
    int dis[maxn]; 
    int fa[maxn]; 
    int cant[maxn];  
    bool used[maxn]; 
    void dij() { 
    	memset(dis,0x3f,sizeof dis); 
    	q.push(mp(dis[1] = 0,1)); 
    	while(!q.empty()) { 
    		int u = q.top().second;q.pop();  
    		for(int i = head[u];i;i = edge[i].next) { 
    			if(used[i] == true) continue; 
    			int v = edge[i].v; 
    			if(dis[v] > dis[u] + edge[i].w) { 
    				dis[v] = dis[u] + edge[i].w; 
    				fa[v] = u; 
    				ner[v] = edge[i].w; 
    				cant[v] = i; 
    				q.push(mp(-dis[v],v)); 
    			} 
    		} 
    	} 
    } 
    int D[maxn]; 
    void dfs(int x) { 
    	for(int i = head[x];i;i = edge[i].next) { 
    		int v = edge[i].v; 
    		if(fa[v] != x && v != fa[x]) 
    		D[x] = std::min(D[x],dis[v] + edge[i].w); 
    	} 
    	for(int i = H[x];i;i = E[i].next) { 
    		int v = E[i].v; 
    		dfs(v); 
    		D[x] = std::min(D[x],D[v] + E[i].w); 
    	} 
    } 
    int pp[maxn]; 
    int main() { 
    	n = read(),m = read(); 
    	for(int u,v,w,i = 1;i <= m;++ i) { 
    		u = read(),v = read(),w = read(); 
    		add_edge(u,v,w); 
    		add_edge(v,u,w); 
    	} 
    	dij(); 
    	if(n <= 1000) { 
    		for(int i = 2;i <= n;++ i)pp[i] = cant[i]; 
    		for(int i = 2;i <= n;++ i) { 
    			used[pp[i]] = used[pp[i] ^ 1] = true; 
    			dij(); 
    			used[pp[i]] = used[pp[i] ^ 1] = false; 	
    			printf("%d
    ",dis[i] == 0x3f3f3f3f ? -1 : dis[i]); 
    		} 
    		return 0; 
    	} 
    	num = 0; 
    	for(int i = 2;i <= n;++ i)  add(fa[i],i,ner[i]); 
    	memset(D,0x3f,sizeof D); 
    	dfs(1); 
    	for(int i = 2;i <= n;++ i) { 
    		printf("%d
    ",D[i] == 0x3f3f3f3f ? -1 : D[i]); 
    	} 
    	return 0; 
    } 
    /* 
    4 5
    1 2 2
    1 3 4
    3 4 4
    3 2 1
    2 4 3
    3
    3
    6
    */ 
    
  • 相关阅读:
    第十四周课程总结&实验报告(简单记事本的实现)
    第十三周课程总结
    第十二周课程总结
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
    第七周课程总结&试验报告(五)
    基于C的
    RMQ 区间最值问题
  • 原文地址:https://www.cnblogs.com/sssy/p/9609624.html
Copyright © 2011-2022 走看看