• [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)


     

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先。第一次写..表示各种乱..

    因为要求运输货物质量最大,所以路径一定是在最大生成树上的。然后就用LCA求两点之间的能运输的最大重量。预处理O(nlogn),查询O(logn).

    ----------------------------------------------------------------------------------------

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cctype>

         

    #define rep(i,n) for(int i=0;i<n;i++)
    #define clr(x,c) memset(x,c,sizeof(x))
    #define Rep(i,l,r) for(int i=l;i<r;i++)
    #define addEdge(u,v,d) MST.edges.push_back((Edge){u,v,d})
    #define jud(a,b) MST.find(a)-MST.find(b)

        

    using namespace std;

        

    const int maxn=10000+5,maxs=20;
    const int inf=0x7fffffff;

        

    struct Edge {
    int u,v,d;
    Edge(int _u,int _v,int _d):u(_u),v(_v),d(_d) {}
    bool operator < (const Edge &x) const {
    return d>x.d;
    }
    };

        

    struct LCA {

             

    int p[maxn][maxs];
    int depth[maxn];
    int d[maxn][maxs];
    bool vis[maxn];
    int n;
    vector<int> g[maxn];
    vector<Edge> edges;
    void init(int _n) {
    n=_n;
    edges.clear();
    rep(i,n) { g[i].clear(); vis[i]=false; }
    }
    void add(int u,int v,int d) {
    edges.push_back( (Edge) {u,v,d} );
    edges.push_back( (Edge) {v,u,d} );
    int m=edges.size();
    g[u].push_back(m-2);
    g[v].push_back(m-1);
    }
    void dfs(int x) {
    int t=1;
    vis[x]=1;
    while(depth[x]>=(1<<t)) {
    p[x][t]=p[p[x][t-1]][t-1];
    d[x][t]=min(d[x][t-1],d[p[x][t-1]][t-1]);
    t++;
    }
    rep(i,g[x].size()) {
    Edge &e=edges[g[x][i]];
    if(vis[e.v]) continue;
    p[e.v][0]=x;
    d[e.v][0]=e.d;
    depth[e.v]=depth[x]+1;
    dfs(e.v);
    }
    }
    void DFS() { rep(i,n) if(!vis[i]) { depth[i]=0; dfs(i); } }
    int query(int a,int b) {
    int tmp,log=1;
    if(depth[a]<depth[b]) swap(a,b);
    while((1<<(log+1))<=depth[a]) log++;
    int ans=inf;
    for(int i=log;i>=0;--i) if(depth[a]-(1<<i)>=depth[b]) {
    ans=min(ans,d[a][i]);
    a=p[a][i];
    }
    if(a==b) return ans;
    for(int i=log;i>=0;--i) if(p[a][i]!=-1 && p[a][i]!=p[b][i]) {
    ans=min(ans,d[a][i]); a=p[a][i];
    ans=min(ans,d[b][i]); b=p[b][i];
    }
    return ans=min(ans,min(d[a][0],d[b][0]));
    }
    };
    LCA lca;
      
    struct KRUSKAL {
    int n;
    int p[maxn];
    vector<Edge> edges;
    void init(int _n) {
    n=_n;
    edges.clear();
    }
    int find(int x) { return x==p[x] ? x : p[x]=find(p[x]); }
    void kruskal() {
    rep(i,n) p[i]=i;
    sort(edges.begin(),edges.end());
    rep(i,edges.size()) {
    Edge &e=edges[i];
    int x=find(e.u),y=find(e.v);
    if(x!=y) {
    p[x]=y;
       lca.add(e.u,e.v,e.d);
    }
    }
    }
    };
      
    KRUSKAL MST;
    int read() {
    char c=getchar();
    int ans=0,f=1;
    while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
    while(isdigit(c)) { (ans*=10)+=c-'0'; c=getchar(); }
    return f*ans;
    }
       
    int main()
    {
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    int n=read(),m=read();
    MST.init(n);
    lca.init(n);
    rep(i,m) {
    int u=read(),v=read(),d=read();
    addEdge(--u,--v,d);
    }
    MST.kruskal();
    lca.DFS();
    n=read();
    rep(i,n) {
    int a=read(),b=read();
    --a; --b;
    if(jud(a,b)) printf("-1 ");
    else {
    printf("%d ",lca.query(a,b));
    }
    }
    return 0;
    }

    ---------------------------------------------------------------------------------------- 

    3287 货车运输

     

    2013年NOIP全国联赛提高组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
  • 相关阅读:
    项目Alpha冲刺Day7
    项目Alpha冲刺Day5
    项目Alpha冲刺Day6
    Alpha冲刺总结
    测试随笔
    项目Alpha冲刺Day12
    高校征信系统项目Postmortem结果
    冲刺合集
    总结随笔
    测试工作安排
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4366837.html
Copyright © 2020-2023  润新知