Aizu 2456 Usoperanto (贪心)
2015-10-02 17:17
495 查看
贪心,对于一个修饰关系可以连一条有向边,在合并的时候,子节点的序列一定是连续安排的,因为如果有交叉,交换以后一定更优。
然后一个序列一个序列的考虑,长度短的应该在前面,否则同样交换以后更优。因此排序以后统计就行了。
数据理论最多递归1e6层,dfs爆栈了,手写栈模拟递归。。。
另外拓扑排序也可以避免递归
然后一个序列一个序列的考虑,长度短的应该在前面,否则同样交换以后更优。因此排序以后统计就行了。
数据理论最多递归1e6层,dfs爆栈了,手写栈模拟递归。。。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; vector<int> G[maxn]; int M[maxn]; typedef long long ll; long long ans; bool cmp(int a,int b) { return M[a] < M[b]; } struct Frame { int u,i; }; stack<Frame> dfs; inline void CreatFrame(int u){ dfs.push({u,0});} #define PS push void DFS(int s) { CreatFrame(s); bool pre = true;//pre or post while(dfs.size()){ loop: int u = dfs.top().u, &i = dfs.top().i; for(; i < (int)G[u].size(); i++){ if(pre) { CreatFrame(G[u][i]); goto loop; } M[u] += M[G[u][i]]; pre = true; } sort(G[u].begin(),G[u].end(),cmp); for(int i = 0; i < (int)G[u].size(); i++){ ans += M[G[u][i]]*((ll)G[u].size()-i-1); } dfs.pop(); pre = false; } } int rts[maxn]; //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif int n; scanf("%d",&n); int c = 0; for(int i = 0; i < n; i++){ int f; scanf("%d%d",M+i,&f); if(~f){ G[f].push_back(i); } else rts[c++] = i; } while(c--){ DFS(rts[c]); } printf("%lld\n",ans); return 0; }
另外拓扑排序也可以避免递归
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; int hd[maxn],nx[maxn],to[maxn],ec; void add(int u,int v) { nx[++ec] = hd[u]; to[ec] = v; hd[u] = ec; } int M[maxn]; int fa[maxn],deg[maxn]; typedef long long ll; int stk[maxn]; int q[maxn]; //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif int n; scanf("%d",&n); int rt = 0; for(int i = 0; i < n; i++){ int f; scanf("%d%d",M+i,&f); if(~f){ add(f,i); deg[f]++; } fa[i] = f; } int frnt = 0, tail = 0; for(int i = 0; i < n; i++){ if(!deg[i]) q[tail++] = i; } long long ans = 0; while(frnt<tail){ int u = q[frnt++]; int top = 0; for(int i = hd[u]; i; i = nx[i]){ stk[top++] = M[to[i]]; } sort(stk,stk+top); for(int i = 0; i < top; i++){ ans += stk[i]*(ll)(top-i-1); } if(~fa[u]){ M[fa[u]] += M[u]; if(!--deg[fa[u]]) q[tail++] = fa[u]; } } printf("%lld\n",ans); return 0; }
相关文章推荐
- UVa 11853 PaintBall
- 在linux进程中的信号屏蔽 http://blog.csdn.net/fjb2080/article/details/5174306
- vfork http://blog.csdn.net/tennysonsky/article/details/45847107
- Light oj 1038 - Race to 1 Again(概率dp)
- Tail call optimization in Scala
- 信号量sem_wait()的使用
- 关于信号量sem_wait的整理(转)
- system()函数 http://blog.csdn.net/ghevinn/article/details/7916126
- waitpid系统调用在Linux函数库中的原型是:http://blog.sina.com.cn/s/blog_602a39250100xfxx.html
- poj2305-Basic remains(进制转换 + 大整数取模)
- HDU 1702 ACboy needs your help again!(栈和队列)
- poj 1995 Raising Modulo Numbers【快速幂】
- 解决:CWnd::SetWindowText报Assertion failure
- AIDL调用第三方应用程序服务中的方法
- wait函数返回值总结http://blog.csdn.net/astrotycoon/article/details/41172389
- system函数的总结 http://blog.csdn.net/astrotycoon/article/details/40626355
- 【MongoDB】2014-07-25T11:00:48.634+0800 warning: Failed to connect to 127.0.0.1:27017, reason: errno:1
- linux避免僵死进程方法总结 http://blog.csdn.net/astrotycoon/article/details/39717143
- waitpid(or wait)和SIGCHILD的关系 http://blog.csdn.net/liuxingen/article/details/38350347
- Linux的system()和popen()差异 http://blog.csdn.net/liuxingen/article/details/47057539