列表

详情


NC51260. Freda 的传呼机

描述

为了随时与 rainbow 快速交流,Freda 制造了两部传呼机。Freda 和 rainbow 所在的地方有 N 座房屋、M 条双向光缆。每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传递,并且传呼机的信号从光缆的其中一端传递到另一端需要花费 t 单位时间。现在 Freda 要进行 Q 次试验,每次选取两座房屋,并想知道传呼机的信号在这两座房屋之间传递至少需要多长时间。Freda 和 rainbow 简直弱爆了有木有 T_T,请你帮帮他们吧……

输入描述

第一行包含三个用空格隔开的整数,N、M 和 Q。
接下来 M 行每行三个整数 x、y、t,表示房屋 x 和 y 之间有一条传递时间为 t 的光缆。
最后 Q 行每行两个整数 x、y,表示 Freda 想知道在 x 和 y 之间传呼最少需要多长时间。

输出描述

输出 Q 行,每行一个整数,表示 Freda 每次试验的结果。

示例1

输入:

5 4 2
1 2 1
1 3 1
2 4 1
2 5 1
3 5
2 1

输出:

3
1

示例2

输入:

5 5 2
1 2 1
2 1 1
1 3 1
2 4 1
2 5 1
3 5
2 1

输出:

3
1

示例3

输入:

9 10 2
1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 9
5 7

输出:

5
6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Java 解法, 执行用时: 125ms, 内存消耗: 17484K, 提交时间: 2021-09-03 23:35:40

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.Collection;
import java.io.IOException;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.Queue;
import java.util.ArrayDeque;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        FredasPager solver = new FredasPager();
        solver.solve(1, in, out);
        out.close();
    }

    static class FredasPager {
        int N = 12005;
        int M = N * 4;
        int[] h = new int[N];
        int[] e = new int[M];
        int[] ne = new int[M];
        int[] w = new int[M];
        int idx;
        int[] dfn = new int[N];
        int[] fa = new int[N];
        int[] dist = new int[N];
        int[] sum = new int[N];
        int[] in = new int[N];
        boolean[] vis = new boolean[N];
        boolean[] broken = new boolean[M];
        int[] lenCycle = new int[N];
        int[] d = new int[N];
        int T = 18;
        int[][] f = new int[N][T];
        int n;
        int m;
        int t;
        int num;
        int cnt;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            Arrays.fill(h, -1);
            idx = 0;
            n = in.nextInt();
            m = in.nextInt();
            t = in.nextInt();
            for (int i = 1; i <= m; i++) {
                int a = in.nextInt();
                int b = in.nextInt();
                int c = in.nextInt();
                add(a, b, c);
                add(b, a, c);
            }

            spfa();
            dfs(1);
            bfs();

            for (int i = 0; i < t; i++) {
                int a = in.nextInt();
                int b = in.nextInt();
                out.println(calc(a, b));
            }

        }

        private int calc(int a, int b) {
            if (d[a] < d[b]) {
                int t = a;
                a = b;
                b = t;
            }
            int oa = a;
            int ob = b;
            for (int i = T - 1; i >= 0; i--) {
                if (d[f[a][i]] >= d[b]) {
                    a = f[a][i];
                }
            }
            if (a == b) {
                return dist[oa] - dist[ob];
            }
            for (int i = T - 1; i >= 0; i--) {
                if (f[a][i] != f[b][i]) {
                    a = f[a][i];
                    b = f[b][i];
                }
            }
            if (in[a] == 0 || in[a] != in[b]) {
                return dist[oa] + dist[ob] - 2 * dist[f[a][0]];
            }
            // 环上某个方向的距离
            int l = Math.abs(sum[a] - sum[b]);
            return dist[oa] - dist[a] + dist[ob] - dist[b] + Math.min(l, lenCycle[in[a]] - l);
        }

        void bfs() {
            Queue<Integer> queue = new ArrayDeque<>();
            queue.add(1);
            d[1] = 1;
            while (!queue.isEmpty()) {
                Integer u = queue.poll();
                for (int i = h[u]; i != -1; i = ne[i]) {
                    int j = e[i];
                    if (d[j] == 0 && !broken[i]) {
                        d[j] = d[u] + 1;
                        f[j][0] = u;
                        for (int k = 1; k < T; k++) {
                            f[j][k] = f[f[j][k - 1]][k - 1];
                        }
                        queue.add(j);
                    }
                }
            }
        }

        private void dfs(int u) {
            dfn[u] = ++num;
            for (int i = h[u]; i != -1; i = ne[i]) {
                int j = e[i];
                if (dfn[j] == 0) {
                    fa[j] = i;
                    dfs(j);
                } else if ((i ^ 1) != fa[u] & dfn[j] >= dfn[u]) {
                    getCycle(u, j, i);
                }
            }
        }

        private void getCycle(int u, int j, int z) {
            cnt++;
            sum[j] = w[z];
            broken[z] = broken[z ^ 1] = true;
            while (j != u) {
                in[j] = cnt;
                int nextJ = e[fa[j] ^ 1];
                sum[nextJ] = sum[j] + w[fa[j]];

                broken[fa[j]] = broken[fa[j] ^ 1] = true;
                add(u, j, dist[j] - dist[u]);
                add(j, u, dist[j] - dist[u]);

                j = nextJ;
            }
            in[u] = cnt;
            lenCycle[cnt] = sum[u];

        }

        void spfa() {
            Arrays.fill(dist, 0x3f3f3f3f);
            dist[1] = 0;
            Queue<Integer> queue = new ArrayDeque<>();
            queue.add(1);
            vis[1] = true;
            while (!queue.isEmpty()) {
                int t = queue.poll();
                vis[t] = false;
                for (int i = h[t]; i != -1; i = ne[i]) {
                    int j = e[i];
                    if (dist[j] > dist[t] + w[i]) {
                        dist[j] = dist[t] + w[i];
                        if (!vis[j]) {
                            queue.add(j);
                            vis[j] = true;
                        }
                    }
                }
            }
        }

        void add(int a, int b, int c) {
            e[idx] = b;
            w[idx] = c;
            ne[idx] = h[a];
            h[a] = idx++;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new UnknownError();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new UnknownError();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new UnknownError();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void println(int i) {
            writer.println(i);
        }

    }
}

C++ 解法, 执行用时: 61ms, 内存消耗: 2700K, 提交时间: 2022-02-25 19:45:36

#include<bits/stdc++.h>
using namespace std;
int x,y,t,n,m,q,to[40001],ntt[40001],last[40001],val[40001],num,nt[40001],nn[40001],nl[40001],nv[40001],cnt,dfn[20001],top,f[20001][15],g[20001][15],fa[20001],c1[20001],c2[20001],bl[20001],zx[20001],zz,d[20001],tt,vis[20001],sbll;
struct stack{int x,s;}st[20001];
void ad(int x,int y,int c){num++;to[num]=y;ntt[num]=last[x];last[x]=num;val[num]=c;}
void nad(int x,int y,int c){cnt++;nt[cnt]=y;nn[cnt]=nl[x];nl[x]=cnt;nv[cnt]=c;}
void dfs(int x){
    dfn[x]=++tt;
    for(int i=last[x];i;i=ntt[i]){
        int v=to[i];
        if(v!=fa[x]&&!dfn[v])fa[v]=x,top++,st[top].x=v,st[top].s=val[i],dfs(v);
        else if(v!=fa[x]&&dfn[v]<dfn[x]){
            zz++;
            int p=top,tmp=val[i];
            while(st[p].x!=v&&p)c1[st[p].x]=tmp,tmp+=st[p].s,p--;
            tmp=st[p+1].s;
            for(int i=p+1;i<=top;i++){zx[st[i].x]=v;bl[st[i].x]=zz;c2[st[i].x]=tmp;int jx=min(c1[st[i].x],c2[st[i].x]);nad(st[i].x,v,jx);nad(v,st[i].x,jx);tmp+=st[i+1].s;}
        }
    }
    top--;
}
void cxlb(int x){
    vis[x]=1;
    for(int i=last[x];i;i=ntt[i]){
        int v=to[i];
        if(v-fa[x]&&!vis[v]){if((bl[x]-bl[v]||!bl[x]&&!bl[v])&&zx[v]-x&&zx[x]-v)nad(x,v,val[i]),nad(v,x,val[i]);cxlb(v);}
    }
}
void find(int x){for(int i=nl[x];i;i=nn[i]){int v=nt[i];if(v-f[x][0])f[v][0]=x,g[v][0]=nv[i],d[v]=d[x]+1,find(v);}}
int lca(int x,int y){
    int tmp=0;
    if(d[x]>d[y]) swap(x,y);
    for(int i=14;i>=0;i--)while(d[f[y][i]]>=d[x])tmp+=g[y][i],y=f[y][i];
    if(x==y)return tmp;
    for(int i=14;i>=0;i--)while(f[x][i]-f[y][i])tmp+=g[x][i]+g[y][i],x=f[x][i],y=f[y][i];
    if(x-y&&bl[x]&&bl[x]==bl[y])tmp+=min(min(c1[x]+c2[y],c1[y]+c2[x]),min(abs(c2[x]-c2[y]),abs(c1[x]-c1[y])));
    else tmp+=g[x][0]+g[y][0];
    return tmp;
}
int main(){
    cin>>n>>m>>q;
    for(int i=1;i<=m;i++)cin>>x>>y>>t,ad(x,y,t),ad(y,x,t);
    dfs(1);
    cxlb(1);
    find(1);
    d[0]=-1;
    for(int j=1;j<=14;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1];
    for(int i=1;i<=q;i++)cin>>x>>y,cout<<lca(x,y)<<"\n";
    return 0;
}

上一题