noip2012:疫情控制

来源:互联网 发布:淘宝拆分订单发货 编辑:程序博客网 时间:2024/05/01 23:28

最近要noip了,只好来鏼noip的题。。。发现自己好弱。。。于是来凑一篇博客。。。

题目要求最小时间,不妨二分。然后很自然地想到每个军队需要暴力向上走,显然越往上越优。然后针对那些能跑到根的拉出来,因为他们可以去根的别的子树也可以留着。

然后贪心,那些可以到根又回来的,索性让他们去根。那些回不来的如果他所在的子树需要他就留下,证明如下:

设根为a,若b的军队去c有解,则去b的军队一定可以去c,那么b的军队留着,去b的军队去c也满足,证毕。

现在我们得到了一堆在根节点的军队和一些根的儿子节点的需求,分别排序即可解决。

好~现在算一波复杂度:暴力跳是O(logn*(n^2+nlogn)),如果倍增跳or树剖跳是O(logn*nlogn)。然后你就得到了一个100分算法。

现在考虑去掉那个logn(就是倍增和排序的那个,二分的并不知道怎么去掉)。把可以到根的节点传送到除根以外的最上面的点,对剩余的点一个树形DP即可。对于根的儿子的排序完全可以预处理之后达到O(n)排序,然后能到根的军队最后的移动力只与出发点的深度有关。于是先把所有军队按出发点深度预处理排序,之后用同样的方法O(n)排序。这样就得到了一个O(nlogn)的优(hei)秀(ke)算(ji)法。然而并没有什么卵用。。。

代码略丑。。没卡过常数,就这样吧。。。

#include<iostream>#include<cstdio>#include<algorithm>#define N 100005using namespace std;int n,m,a[N],b[N],c[N],d[N],Fa[N],x,y;int first[N],nxt[N],to[N],len[N],l;int top[N],ord[N],size[N],cnt,v[N],dep[N],fa[N],Bson[N];int val[N],p[N];int Getfa(int x){return Fa[x]==x?x:Fa[x]=Getfa(Fa[x]);}bool cmp(int x,int y){return c[x]>c[y];}void link(int x,int y,int z){to[++l]=y;len[l]=z;nxt[l]=first[x];first[x]=l;to[++l]=x;len[l]=z;nxt[l]=first[y];first[y]=l;}void dfs(int x){dep[x]=dep[fa[x]]+1;size[x]=1;for (int i=first[x];i;i=nxt[i])if (to[i]!=fa[x]){fa[to[i]]=x;v[to[i]]=len[i];dfs(to[i]);size[x]+=size[to[i]];if (size[to[i]]>size[Bson[x]]) Bson[x]=to[i];}}void dfs(int x,int y){top[x]=y;ord[x]=++cnt;val[cnt]=v[x];if (Bson[x]) dfs(Bson[x],y);for (int i=first[x];i;i=nxt[i])if (to[i]!=fa[x]&&to[i]!=Bson[x])dfs(to[i],to[i]);}void build(int k,int l,int r){if (l==r){p[k]=val[l];//cout<<l<<' '<<p[k]<<endl;return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);p[k]=min(p[k<<1],p[k<<1|1]);}int qry(int k,int l,int r,int x,int y){if (x<=l&&r<=y)return p[k];int mid=l+r>>1,ans=1000000000;if (x<=mid) ans=qry(k<<1,l,mid,x,y);if (y>mid) ans=min(ans,qry(k<<1|1,mid+1,r,x,y));return ans;}int qry(int x,int y){int ans=1000000000;for (;top[x]!=top[y];ans=min(ans,qry(1,1,n,ord[top[x]],ord[x])),x=fa[top[x]])if (dep[top[x]]<dep[top[y]]) swap(x,y);if (dep[x]>dep[y]) swap(x,y);if (x!=y) ans=min(ans,qry(1,1,n,ord[x]+1,ord[y]));return ans;}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=m;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]),d[i]=i;for (int i=1;i<=n;i++)Fa[i]=i;sort(d+1,d+m+1,cmp);for (int i=1;i<=m;i++){int u=Getfa(a[d[i]]),v=Getfa(b[d[i]]);if (u!=v)link(a[d[i]],b[d[i]],c[d[i]]),Fa[u]=v;}for (int i=1;i<=n;i++)if (!size[i])dfs(i),dfs(i,i);build(1,1,n);scanf("%d",&m);for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);if (Getfa(x)==Getfa(y))printf("%d\n",qry(x,y));else puts("-1");}//while(1);}


0 0