51nod 1307
来源:互联网 发布:郭德纲网络剧 编辑:程序博客网 时间:2024/06/01 14:26
题意:给出一棵树,每条边上都有一个权值,每个点也有一个权值,当一条边的子树所有节点权值和超过这条边的权值时,这条边会断开。边按序给出,问最多能有几条边。
每条边的可承受重量可以看成其下端点的可承受重量。
数据比较弱,首先可以按题意模拟,当加入一个新点时,向上不断查找父节点,查看新点到根节点的这条路径是否有边会超限断开。
#include<cstdio>#include<cstring>#include<iostream>#define LL long longusing namespace std;const int maxn=5e4+50;const int maxe=5e4+50;const LL Inf=1e18;int r[maxn], w[maxn], p[maxn];int n;int main(){ int par; int ans=-1; scanf("%d", &n); for(int i=1;i<=n;i++){ scanf("%d%d%d", &r[i], &w[i], &p[i]); p[i]++; if(ans>=0) continue; int v=i, tw=w[i]; while(v){ r[v]-=tw; if(r[v]<0) ans=i-1; v=p[v]; } } if(ans==-1) ans=n; printf("%d\n", ans); return 0;}
但上面那种方法的复杂度是O(n^2)的,在整棵树退化成一条链的时候,n=50000时耗时6s+。
最大值问题,考虑二分,每次二分出来的值可以通过一次深搜来验证。
#include<cstdio>#include<cstring>#include<iostream>#define LL long longusing namespace std;const int maxn=5e4+50;const int maxe=5e4+50;const LL Inf=1e18;struct Edge{ int from, to, next;};Edge edges[maxe];int head[maxn], ecnt;int n;LL r[maxn], w1[maxn], w2[maxn];bool flag;void add_edge(int u,int v){ edges[ecnt]=Edge{u, v, head[u]}; head[u]=ecnt++;}void dfs(int u,int lim){ if(!flag) return; LL &tmp=w2[u]; tmp=w1[u]; for(int i=head[u];i!=-1;i=edges[i].next) if(i<=lim){ int v=edges[i].to; dfs(v, lim); if(!flag) return; tmp+=w2[v]; } if(tmp>r[u]) flag=false;}void init(){ int par; memset(head, -1, sizeof head); ecnt=1; scanf("%d", &n); for(int i=1;i<=n;i++){ scanf("%lld%lld%d", &r[i], &w1[i], &par); par++; add_edge(par, i); } w1[0]=0; r[0]=Inf;}void solve(){ int l=1, r=n; int ans=0; while(l<=r){ int mid=(l+r)>>1; flag=true; dfs(0, mid); if(flag){ ans=mid; l=mid+1; }else{ r=mid-1; } } printf("%d\n", ans);}int main(){ init(); solve(); return 0;}
但上面的代码在树深度过深时,比如n=50000且退化成一条链时,会爆栈。把递归深搜改成循环,把使用系统栈改成使用STL的栈。
#pragma comment (linker,"/stack:102400000,102400000")#include<stack>#include<queue>#include<cstdio>#include<cstring>#include<iostream>#define LL long longusing namespace std;const int maxn=5e4+50;const int maxe=5e4+50;const LL Inf=1e18;struct Edge{ int from, to, next;};Edge edges[maxe];int head[maxn], ecnt;int n;LL r[maxn], w1[maxn], w2[maxn];bool flag;stack<int> S;queue<int> Q;void add_edge(int u,int v){ edges[ecnt]=Edge{u, v, head[u]}; head[u]=ecnt++;}void dfs(int x,int lim){ Q.push(x); while(!Q.empty()){ int u=Q.front(); Q.pop(); S.push(u); for(int i=head[u];i!=-1;i=edges[i].next) if(i<=lim){ int v=edges[i].to; Q.push(v); } } while(!S.empty()){ int u=S.top(); S.pop(); LL &tmp=w2[u]; tmp=w1[u]; for(int i=head[u];i!=-1;i=edges[i].next) if(i<=lim){ int v=edges[i].to; tmp+=w2[v]; if(tmp>r[u]) flag=false; if(!flag) return; } }}void init(){ int par; memset(head, -1, sizeof head); ecnt=1; scanf("%d", &n); for(int i=1;i<=n;i++){ scanf("%lld%lld%d", &r[i], &w1[i], &par); par++; add_edge(par, i); } w1[0]=0; r[0]=Inf;}void solve(){ //puts("Infinity is awesome!"); int l=1, r=n; int ans=0; while(l<=r){ int mid=(l+r)>>1; flag=true; dfs(0, mid); if(flag){ ans=mid; l=mid+1; }else{ r=mid-1; } } printf("%d\n", ans);}int main(){ //freopen("data.txt", "r", stdin); init(); solve(); return 0;}
阅读全文
0 0
- 51nod 1307
- 51Nod
- 51Nod
- 51nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 变量的名义
- Ubuntu16.04从零搭建lamp环境,再到跑通laravel项目
- QByteArray与QString之间的相互转换
- setTimeout和setInterval的区别
- 《加密与解密》笔记三(一)
- 51nod 1307
- processing编程【1】
- 数组
- 如何转载他人的博客
- NDK编译——NEON支持
- 有时候在一个div中写了文字,当想给div加上padding值时,文字不会居中的现象
- DBNAVIGATOR使用
- oracle_DBA_临时表_约束
- 斯人若彩虹,遇上方知有