zoukankan      html  css  js  c++  java
  • 【NOIP2013】货车运输

    感觉这题挺水的……真的挺水的……

    原题:

    A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

    思路非常简单,求最大生成树,然后剖,甚至连修改操作都没有

    这题水啊,二分就有60,正解就是个裸的生成树+剖

    如果NOIP考自己学过的比较高级的高级数据结构是一件挺好的事,受到NOIP难度的限制,考比较高级的东西的话就会裸得多,就没有呢么多魔性的东西了(然而因为选手水平提升而难度增加的概率非常大QAQ)

    有几点需要注意的地方,因为这里要用点的权值当边的权值,所以在路径遇到拐点(就是deep[x]>deep[y]<deep[z])的时候要特判一下,首先如果最后到一条重链上的时候x和y一样的话就不找了,因为这个点就是拐点,查找的话结果会是拐点和它的父节点之间的边,就跟路径没关系了,如果查找的话,查找左端点要是深度比较浅的内个点的标号+1,因为深度比较浅的内个点的值是它和它父节点之间连的边的值,但是在往同一个重链上攀的时候就不用这么判断了,因为不+1的话刚好把重链顶点和它的父节点之间的边算上了,就不用再算一遍了

    第一次写成树剖,这个东西终于懂了QAQ,收货还是挺多的

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 using namespace std;
      7 int read(){int z=0,mark=1;  char ch=getchar();
      8     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
      9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
     10     return z*mark;
     11 }
     12 struct ddd{int next,y,value;}e[1100000];int LINK[110000],ltop=0;
     13 inline void insert(int x,int y,int z){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;e[ltop].value=z;}
     14 struct ccc{int x,y,value;}tu[110000];int tltop=0;
     15 inline void insert_tu(int x,int y,int z){tu[++tltop].x=x,tu[tltop].y=y,tu[tltop].value=z;}
     16 struct dcd{int sleft,sright,mid,svalue;}tree[1100000];
     17 int n,m;
     18 int size[110000],deep[110000],father[110000],big_child[110000],top[11000];
     19 int dfs_xv[110000],fan_xv[110000],cnt=0,b_value[110000];
     20 int ji[110000];
     21 int group[110000],gtop=0;
     22 int cha(int x){  if(ji[x]==x)  return x;  ji[x]=cha(ji[x]);  return ji[x];}
     23 void bing(int x,int y){  int ji_x=cha(x),ji_y=cha(y);  ji[ji_x]=ji_y;}
     24 bool compare(ccc x,ccc y){  return x.value>y.value;}//这里求的是最大生成树
     25 void kruskal(){
     26     for(int i=1;i<=n;i++)  ji[i]=i;
     27     sort(tu+1,tu+tltop+1,compare);
     28     int _cnt=0;
     29     for(int i=1;i<=tltop;i++){
     30         int _x=cha(tu[i].x),_y=cha(tu[i].y);
     31         if(_x!=_y){
     32             bing(_x,_y);
     33             insert(tu[i].x,tu[i].y,tu[i].value),insert(tu[i].y,tu[i].x,tu[i].value);
     34             if(++_cnt==n-1)  return ;
     35         }
     36     }
     37 }
     38 void dfs1(int x,int _deep,int _father){
     39     group[x]=gtop;
     40     father[x]=_father,deep[x]=_deep,size[x]=1;
     41     int max_size=0,max_child=0;
     42     for(int i=LINK[x];i;i=e[i].next)if(e[i].y!=_father){
     43         dfs1(e[i].y,_deep+1,x);
     44         b_value[e[i].y]=e[i].value;
     45         size[x]+=size[e[i].y];
     46         if(size[e[i].y]>max_size){  max_size=size[e[i].y];  max_child=e[i].y;}
     47     }
     48     big_child[x]=max_child;
     49 }
     50 void dfs2(int x,int _top){
     51     top[x]=_top;  dfs_xv[++cnt]=x;  fan_xv[x]=cnt;
     52     if(big_child[x])  dfs2(big_child[x],_top);
     53     for(int i=LINK[x];i;i=e[i].next)if(e[i].y!=father[x] && e[i].y!=big_child[x])
     54         dfs2(e[i].y,e[i].y);
     55 }
     56 void get_SegmentTree(int x,int _left,int _right){
     57     tree[x].sleft=_left,tree[x].sright=_right,tree[x].mid=(_left+_right)>>1;
     58     if(_left==_right)  tree[x].svalue=b_value[dfs_xv[_left]];//注意这里
     59     else{
     60         get_SegmentTree(x<<1,_left,tree[x].mid),get_SegmentTree(x<<1|1,tree[x].mid+1,_right);
     61         tree[x].svalue=min(tree[x<<1].svalue,tree[x<<1|1].svalue);
     62     }
     63 }
     64 int search(int x,int _left,int _right){
     65     if(tree[x].sleft==_left && tree[x].sright==_right)  return tree[x].svalue;
     66     else if(_left<=tree[x].mid && _right>tree[x].mid)  return min(search(x<<1,_left,tree[x].mid),search(x<<1|1,tree[x].mid+1,_right));
     67     else if(_right<=tree[x].mid)  return search(x<<1,_left,_right);
     68     else  return search(x<<1|1,_left,_right);
     69 }
     70 int pa(int x,int y){
     71     int minn=999999999;
     72     int fa=top[x],fb=top[y];
     73     while(fa!=fb){
     74         if(deep[fa]<deep[fb])  swap(fa,fb),swap(x,y);
     75         minn=min(minn,search(1,fan_xv[fa],fan_xv[x]));//注意这里是x
     76         x=father[fa];  fa=top[x];
     77     }
     78     if(deep[x]>deep[y])  swap(x,y);
     79     if(x!=y)  minn=min(minn,search(1,fan_xv[x]+1,fan_xv[y]));//注意,如果不加判断会把拐点和拐点的父节点之间的连边也算进去,而且注意+1
     80     return minn;
     81 }
     82 int main(){//freopen("ddd.in","r",stdin);  freopen("ddd.out","w",stdout);
     83     memset(group,0,sizeof(group));
     84     cin>>n>>m;
     85     int _left,_right,_value;
     86     while(m --> 0){//趋向于
     87         _left=read(),_right=read(),_value=read();
     88         insert_tu(_left,_right,_value);
     89     }
     90     kruskal();
     91     for(int i=1;i<=n;i++)if(!group[i]){  b_value[i]=999999999;  gtop++,dfs1(i,1,0),dfs2(i,i);}//注意连通图问题
     92     get_SegmentTree(1,1,n);
     93     cin>>m;
     94     /*for(int i=1;i<=n;i++)  cout<<b_value[i]<<" ";
     95     cout<<endl;
     96     for(int i=1;i<=n;i++)  cout<<father[i]<<' ';
     97     cout<<endl;*/
     98     while(m --> 0){//趋向于
     99         _left=read(),_right=read();
    100         if(group[_left]==group[_right])  printf("%d
    ",pa(_left,_right));
    101         else  printf("-1
    ");
    102     }
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/JSL2018/p/5900421.html
Copyright © 2011-2022 走看看