noip运输计划(倍增lca,树上差分)

来源:互联网 发布:java实现多线程同步 编辑:程序博客网 时间:2024/05/29 14:51

 

知道思路之后确实不难写,

感觉思路真心不好想,对于最大值最小,二分应该要反应过来

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using namespace std;int n,m,mx,num;struct aa{int u,v,dis,lca;bool operator <(const aa &b)const {return dis<b.dis;}}a[100005];int head[100005],tot,dis[100005];struct aaa{int to,pre,dis;}edge[200005];void addedge(int u,int v,int dis){edge[++tot].to=v;edge[tot].pre=head[u];edge[tot].dis=dis;head[u]=tot;}int dep[100005],fa[100005][20],id[100005],bj[100005];void dfs(int u,int depth,int length){dis[u]=length;dep[u]=depth;for (int i=1;i<=18;i++) fa[u][i]=fa[fa[u][i-1]][i-1];for (int i=head[u];i;i=edge[i].pre)if (dep[edge[i].to]==0){fa[edge[i].to][0]=u;dfs(edge[i].to,depth+1,length+edge[i].dis);}}void up(int &u,int tmp){for (int i=0;i<=18;i++) if (tmp&(1<<i)) u=fa[u][i];}int LCA(int u,int v){if (dep[u]>dep[v]) up(u,dep[u]-dep[v]);else up(v,dep[v]-dep[u]);for (int i=18;i>=0;i--)if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];if (u!=v) return fa[u][0];else return u;}void dfs2(int u){bj[u]=0;for (int i=head[u];i;i=edge[i].pre)if (dep[edge[i].to]==dep[u]+1){dfs2(edge[i].to);if (bj[edge[i].to]==num) mx=max(mx,edge[i].dis);bj[u]+=bj[edge[i].to];}bj[u]+=id[u];}bool pan(int mid){memset(id,0,sizeof(id));num=0;for (int i=m;i>=1;i--)if (a[i].dis>mid) {num++;id[a[i].u]++;id[a[i].v]++;id[a[i].lca]-=2;}else break;mx=0;dfs2(1);//printf("%d %d %d\n",num,mx,mid);if (a[m].dis-mx<=mid) return true;else return false;}int main(){scanf("%d%d",&n,&m);int x,y,z;for (int i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);addedge(x,y,z);addedge(y,x,z);}dfs(1,1,0);for (int i=1;i<=m;i++) {scanf("%d%d",&a[i].u,&a[i].v);a[i].lca=LCA(a[i].u,a[i].v);a[i].dis=dis[a[i].u]+dis[a[i].v]-2*dis[a[i].lca];//printf("%d %d\n",a[i].lca,a[i].dis);}sort(a+1,a+m+1);//for (int i=1;i<=m;i++) printf("%d %d\n",a[i].lca,a[i].dis);int l=0,r=a[m].dis+2,mid,ans;while (l<=r){mid=(l+r)>>1;if (pan(mid)) ans=mid,r=mid-1;else l=mid+1;}printf("%d",ans);return 0;}


 

0 0
原创粉丝点击