zoukankan      html  css  js  c++  java
  • NOIp2013 货车运输 By cellur925

    题目传送门

    A 国有 n 座城市,编号从 1 到 n ,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。

    现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    思路

    这题思路想明白了就很简单,一句话题意:求树上两点间路线中边长最小的边权。

    首先,为什么是树呢?限重肯定越大越好,因此我们可以跑出图的最大生成树(Kruskal)

    之后,我们就可以对于每次询问来求出路径上的最小边权(最多能运的货物重量),这里可以用到树上倍增法(求LCA时一起求了,虽然LCA不会直接用到,但也是要一起求出来的)

    至于两点间是否能互达,就可以用并查集维护一下就行了!

    实现


    提交记录过于真实,从0到10到65到70到95到AC Orz

    可能是我常数写丑了,所以在洛谷更新评测姬前以及不开氧气优化都会T两个点??

    code

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<queue>
      4 #include<cmath>
      5 #include<cstring>
      6 #define maxm 50090
      7 #define maxn 10090
      8 
      9 using namespace std;
     10 
     11 int n,m,Q,tot,t;
     12 int head[maxn],d[maxn],f[maxn][31],fa[maxn],g[maxn][31];
     13 bool vis[maxn];
     14 struct cellur{
     15     int f,t,w;
     16 }e[maxm];
     17 struct node{
     18     int to,next,val;
     19 }edge[maxn<<1];
     20 
     21 bool cmp(cellur a,cellur b)
     22 {
     23     return a.w>b.w;
     24 } 
     25 
     26 void add(int x,int y,int z)
     27 {
     28     edge[++tot].to=y;
     29     edge[tot].next=head[x];
     30     head[x]=tot;
     31     edge[tot].val=z;
     32 }
     33 
     34 int getf(int x)
     35 {
     36     if(fa[x]==x) return x;
     37     else return fa[x]=getf(fa[x]);
     38 }
     39 
     40 void Kruskal()
     41 {
     42     for(int i=1;i<=n;i++) fa[i]=i;
     43     sort(e+1,e+1+m,cmp);
     44     int cnt=0;
     45     for(int i=1;i<=m;i++)
     46     {
     47         if(cnt==n-1) break;
     48         int pp=getf(e[i].f);
     49         int qq=getf(e[i].t);
     50         if(pp==qq) continue;
     51         cnt++;
     52         fa[qq]=pp;
     53         add(e[i].f,e[i].t,e[i].w),add(e[i].t,e[i].f,e[i].w);
     54     }
     55 }
     56 
     57 void bfs(int s)
     58 {
     59     queue<int>q;
     60     q.push(s);d[s]=1;
     61     while(!q.empty())
     62     {
     63         int u=q.front();q.pop();
     64         for(int i=head[u];i;i=edge[i].next)
     65         {
     66             int v=edge[i].to;
     67             if(d[v]) continue;
     68             d[v]=d[u]+1;
     69             f[v][0]=u;g[v][0]=edge[i].val;
     70             for(int j=1;j<=t;j++)
     71             {
     72                 f[v][j]=f[f[v][j-1]][j-1];
     73                 g[v][j]=min(g[f[v][j-1]][j-1],g[v][j-1]);
     74             }
     75             q.push(v);
     76         }
     77     }
     78 }
     79 
     80 int lca(int x,int y)
     81 {
     82     int num=1e9;
     83     if(d[x]<d[y]) swap(x,y);
     84     for(int i=t;i>=0;i--)
     85         if(d[f[x][i]]>=d[y]) num=min(num,g[x][i]),x=f[x][i];
     86     if(x==y) return num;
     87     for(int i=t;i>=0;i--)
     88         if(f[x][i]!=f[y][i])
     89         {
     90             num=min(num,g[x][i]);
     91             num=min(num,g[y][i]);
     92             x=f[x][i],y=f[y][i];
     93         } 
     94     return min(num,min(g[x][0],g[y][0]));
     95 }
     96 
     97 int main()
     98 {
     99     freopen("truck.in","r",stdin);
    100     freopen("truck.out","w",stdout);
    101     scanf("%d%d",&n,&m);
    102     t=log2(n)+1;
    103     for(int i=1;i<=m;i++)
    104         scanf("%d%d%d",&e[i].f,&e[i].t,&e[i].w);
    105     Kruskal();
    106     memset(g,63,sizeof(g));
    107     for(int i=1;i<=n;i++) if(!d[i]) bfs(i);
    108 //    for(int i=1;i<=n;i++) printf("%d ",g[i][2]);
    109 //    return 0;
    110     scanf("%d",&Q);
    111     while(Q--)
    112     {
    113         int x=0,y=0;
    114         scanf("%d%d",&x,&y);
    115         int pp=getf(x);
    116         int qq=getf(y);
    117         if(pp!=qq) {printf("-1
    ");continue;}    
    118         printf("%d
    ",lca(x,y));
    119     }
    120     return 0;
    121 }
    View Code

    $bfs$也能解决不连通的问题:不bfs一次,而是让每个点都有深度。

    11.6考试的时候边大小开小了&&LCA写错板子了hhh

  • 相关阅读:
    mysql5大引擎之间的区别和优劣之分
    关于集合
    泛型
    集合2
    easyui 入门讲解
    <input>和<textarea>
    php中echo(),print(),print_r(),var_dump()间的区别
    PHP图形操作之生成图像验证码
    JZ046圆圈中最后剩下的数
    Python3连接MySQL
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9504852.html
Copyright © 2011-2022 走看看