【NOIP2013】货车运输
2016-09-23 16:04
267 查看
感觉这题挺水的……真的挺水的……
原题:
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,收货还是挺多的
代码:
View Code
原题:
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,收货还是挺多的
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int read(){int z=0,mark=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')mark=-1; ch=getchar();} while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} return z*mark; } struct ddd{int next,y,value;}e[1100000];int LINK[110000],ltop=0; 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;} struct ccc{int x,y,value;}tu[110000];int tltop=0; inline void insert_tu(int x,int y,int z){tu[++tltop].x=x,tu[tltop].y=y,tu[tltop].value=z;} struct dcd{int sleft,sright,mid,svalue;}tree[1100000]; int n,m; int size[110000],deep[110000],father[110000],big_child[110000],top[11000]; int dfs_xv[110000],fan_xv[110000],cnt=0,b_value[110000]; int ji[110000]; int group[110000],gtop=0; int cha(int x){ if(ji[x]==x) return x; ji[x]=cha(ji[x]); return ji[x];} void bing(int x,int y){ int ji_x=cha(x),ji_y=cha(y); ji[ji_x]=ji_y;} bool compare(ccc x,ccc y){ return x.value>y.value;}//这里求的是最大生成树 void kruskal(){ for(int i=1;i<=n;i++) ji[i]=i; sort(tu+1,tu+tltop+1,compare); int _cnt=0; for(int i=1;i<=tltop;i++){ int _x=cha(tu[i].x),_y=cha(tu[i].y); if(_x!=_y){ bing(_x,_y); insert(tu[i].x,tu[i].y,tu[i].value),insert(tu[i].y,tu[i].x,tu[i].value); if(++_cnt==n-1) return ; } } } void dfs1(int x,int _deep,int _father){ group[x]=gtop; father[x]=_father,deep[x]=_deep,size[x]=1; int max_size=0,max_child=0; for(int i=LINK[x];i;i=e[i].next)if(e[i].y!=_father){ dfs1(e[i].y,_deep+1,x); b_value[e[i].y]=e[i].value; size[x]+=size[e[i].y]; if(size[e[i].y]>max_size){ max_size=size[e[i].y]; max_child=e[i].y;} } big_child[x]=max_child; } void dfs2(int x,int _top){ top[x]=_top; dfs_xv[++cnt]=x; fan_xv[x]=cnt; if(big_child[x]) dfs2(big_child[x],_top); for(int i=LINK[x];i;i=e[i].next)if(e[i].y!=father[x] && e[i].y!=big_child[x]) dfs2(e[i].y,e[i].y); } void get_SegmentTree(int x,int _left,int _right){ tree[x].sleft=_left,tree[x].sright=_right,tree[x].mid=(_left+_right)>>1; if(_left==_right) tree[x].svalue=b_value[dfs_xv[_left]];//注意这里 else{ get_SegmentTree(x<<1,_left,tree[x].mid),get_SegmentTree(x<<1|1,tree[x].mid+1,_right); tree[x].svalue=min(tree[x<<1].svalue,tree[x<<1|1].svalue); } } int search(int x,int _left,int _right){ if(tree[x].sleft==_left && tree[x].sright==_right) return tree[x].svalue; 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)); else if(_right<=tree[x].mid) return search(x<<1,_left,_right); else return search(x<<1|1,_left,_right); } int pa(int x,int y){ int minn=999999999; int fa=top[x],fb=top[y]; while(fa!=fb){ if(deep[fa]<deep[fb]) swap(fa,fb),swap(x,y); minn=min(minn,search(1,fan_xv[fa],fan_xv[x]));//注意这里是x x=father[fa]; fa=top[x]; } if(deep[x]>deep[y]) swap(x,y); if(x!=y) minn=min(minn,search(1,fan_xv[x]+1,fan_xv[y]));//注意,如果不加判断会把拐点和拐点的父节点之间的连边也算进去,而且注意+1 return minn; } int main(){//freopen("ddd.in","r",stdin); freopen("ddd.out","w",stdout); memset(group,0,sizeof(group)); cin>>n>>m; int _left,_right,_value; while(m --> 0){//趋向于 _left=read(),_right=read(),_value=read(); insert_tu(_left,_right,_value); } kruskal(); for(int i=1;i<=n;i++)if(!group[i]){ b_value[i]=999999999; gtop++,dfs1(i,1,0),dfs2(i,i);}//注意连通图问题 get_SegmentTree(1,1,n); cin>>m; /*for(int i=1;i<=n;i++) cout<<b_value[i]<<" "; cout<<endl; for(int i=1;i<=n;i++) cout<<father[i]<<' '; cout<<endl;*/ while(m --> 0){//趋向于 _left=read(),_right=read(); if(group[_left]==group[_right]) printf("%d\n",pa(_left,_right)); else printf("-1\n"); } return 0; }
View Code
相关文章推荐
- NOIP2013货车运输
- [Noip2013] 货车运输
- NOIP2013 D1 T3 货车运输 树上倍增lca+Kruskal
- 【NOIP2013-D1T3】货车运输
- 【NOIP2013】货车运输
- 【noip 2013】货车运输
- NOIP 2013 货车运输
- NOIP2013 Day1 T3 货车运输
- [NOIP2013]货车运输 D1 T3 kruscal最大生成树+树上倍增lca+rmq
- 省选专练[SCOI2013]摩托车交易[NOIP2013]货车运输
- noip2013 货车运输题解
- NOIP 2013 货车运输 (树链剖分)
- [noip2013] 货车运输(最大生成树+并查集+LCA)
- NOIP 2013 CODE[VS] 3287 货车运输 倍增LCA + 最大生成树
- noip2013 货车运输
- 洛谷 P1967 Vijos P1843 CODE[VS] P3287 [NOIP2013 D1T3] 货车运输
- 【NOIP2013货车运输】
- 【题解】NOIP 2013 货车运输(最小生成树+LCA)
- NOIP 2013 货车运输
- [NOIp2013] 货车运输