【暑假】[深入动态规划]UVa 1380 A Scheduling Problem

时间:2022-09-07 17:34:26

 UVa 1380 A Scheduling Problem

题目:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41557

思路:

  给出一个任务调度树,单向边u->v表示u必须在v之前完成,双向边u-v表示无所谓方向。

题目给出定理,首先dfs求得忽略无向边后的最长链点数k,那么问题就是判断是否可以通过无向边定向从而使得最长链点数不超过k。用dp的判断。

设f[i]表示以i为根的子树中所有的边定向后最长链点数不超过k条件下出边中最长链的最小值,g[i]表示以i为根的子树中所有的边定向后最长链点数不超过k条件下入边中最长链的最小值(最小值是最低限度,如果最小值都不可行那么问题不可行)。

两种情况(w为子节点):

  1. 与w的边中没有双向边:得出w.f_max与w.g_max判断与k的大小关系 如果超过k 回值INF否则回值w.f_max与w.g_max(max代表最长链)。没有选择的情况,已经定形
  2. 与w的边中有双向边:定向双向边使满足k的限定下f与g尽量小。批量定向,求解f[u]的时候,将w按照f从小到大排序,依此枚举p,对于p将p之前的定向为出边,计算f[u]。同理求解g[u]。最后判断与k的关系。根据双向边定向选择最优结果

代码:

 // UVa1380 A Scheduling Problem
// Rujia Liu
#include<iostream>
#include<string>
#include<cstring>
#include<sstream>
#include<vector>
#include<algorithm>
using namespace std; const int maxn = + ;
const int INF = ; struct Edge {
int u, v, d; // d=1 means u->v, d=2 means v->u, d=0 means u-v
Edge(int u=, int v=, int d=):u(u),v(v),d(d){}
}; vector<Edge> edges[maxn];
int n, root, maxlen, f[maxn], g[maxn], have_father[maxn]; // maximal length of a DIRECTED path starting from u
int dfs(int u) {
int ans = ;
for(int i = ; i < edges[u].size(); i++) {
int v = edges[u][i].v;
if(edges[u][i].d == ) //u->v
ans = max(ans, dfs(v)+);
}
return ans;
} bool read_data() {
bool have_data = false;
int a, b;
n = ;
for(int i = ; i < maxn; i++) edges[i].clear();
memset(have_father, , sizeof(have_father)); while(cin >> a && a){
string str;
have_data = true;
if(a > n) n = a;
while(cin >> str && str != ""){
int len = str.length();
char dir = str[len-];
if(dir == 'd' || dir == 'u') str = str.substr(, len-);
stringstream ss(str);
ss >> b; // b is a's son
if(b > n) n = b;
have_father[b] = ;
if(dir == 'd'){
edges[a].push_back(Edge(a, b, )); // forward
edges[b].push_back(Edge(b, a, )); // backward
}else if(dir == 'u'){
edges[a].push_back(Edge(a, b, ));
edges[b].push_back(Edge(b, a, ));
}else{
edges[a].push_back(Edge(a, b, )); // it's a rooted tree, so we don't store edge to father
}
}
}
if(have_data) {
for(int i = ; i <= n; i++)
if(!have_father[i] && !edges[i].empty()) { root = i; break; }
}
return have_data;
} struct UndirectedSon {
int w, f, g;
UndirectedSon(int w=, int f=, int g=):w(w),f(f),g(g){}
}; bool cmp_f(const UndirectedSon& w1, const UndirectedSon& w2) {
return w1.f < w2.f;
} bool cmp_g(const UndirectedSon& w1, const UndirectedSon& w2) {
return w1.g < w2.g;
} // calculate f[i] and g[i]
// return true iff f[i] < INF
// f[i] is the minimal length of the longest "->u" path if all subtree paths have length <= maxlen
// g[i] is the minimal length of the longest "u->" path if all subtree paths have length <= maxlen
// f[i] = g[i] = INF if "all subtree paths have length <= maxlen" cannot be satisfied
bool dp(int i, int fa) {
if(edges[i].empty()) {
f[i] = g[i] = ;
return true;
}
vector<UndirectedSon> sons;
int f0 = , g0 = ; // f'[i] and g'[i] for directed sons // let f'[i] = max{f[w] | w->i}+1, g'[i] = max{g[w] | i->w}+1
// then we should change some undirected edges to ->u or u-> edges so that f'[i]+g'[i] <= maxlen
// then f[i] is the minimal f'[i] under this condition, and g[i] is the minimal g'[i]
for(int k = ; k < edges[i].size(); k++) {
int w = edges[i][k].v;
if(w == fa) continue; //ch != fa
dp(w, i); //Çó½âÍê×Ó½ÚµãºóÇó½âµ±Ç°½áµã
int d = edges[i][k].d;
if(d == ) sons.push_back(UndirectedSon(w, f[w], g[w]));
else if(d == ) g0 = max(g0, g[w]+);
else f0 = max(f0, f[w]+);
}
// If there is no undirected edges, we're done
if(sons.empty()) {
f[i] = f0; g[i] = g0;
if(f[i] + g[i] > maxlen) { f[i] = g[i] = INF; }
return f[i] < INF;
} f[i] = g[i] = INF; // to calculate f[i], we sort f[w] of undirected sons in increasing order and make first p edges to w->i
// then we calculate f'[i] and g'[i], check for f'[i]+g'[i] <= maxlen and update answer
int s = sons.size();
sort(sons.begin(), sons.end(), cmp_f);
int maxg[maxn]; // maxg[i] is max{sons[i].g, sons[i+1].g, ...}
maxg[s-] = sons[s-].g;
for(int k = s-; k >= ; k--)
maxg[k] = max(sons[k].g, maxg[k+]);
for(int p = ; p <= sons.size(); p++) {
int ff = f0, gg = g0;
if(p > ) ff = max(ff, sons[p-].f+);
if(p < sons.size()) gg = max(gg, maxg[p]+);
if(ff + gg <= maxlen) f[i] = min(f[i], ff);
} // g[i] is similar
sort(sons.begin(), sons.end(), cmp_g);
int maxf[maxn]; // maxf[i] is max{sons[i].f, sons[i+1].f, ...}
maxf[s-] = sons[s-].f;
for(int k = s-; k >= ; k--)
maxf[k] = max(sons[k].f, maxf[k+]);
for(int p = ; p <= sons.size(); p++) {
int ff = f0, gg = g0;
if(p > ) gg = max(gg, sons[p-].g+);
if(p < sons.size()) ff = max(ff, maxf[p]+);
if(ff + gg <= maxlen) g[i] = min(g[i], gg);
} return f[i] < INF;
} int main() {
while(read_data()) {
maxlen = ;
for(int i = ; i <= n; i++) maxlen = max(maxlen, dfs(i));
// Note: the problem asks for the number of nodes in path, but all the "lengths" above mean "number of edges"
if(dp(root, -)) cout << maxlen+ << "\n";
else cout << maxlen+ << "\n";
}
return ;
}

Code from Rujia

【暑假】[深入动态规划]UVa 1380 A Scheduling Problem的更多相关文章

  1. UVA&Tab;1380 A Scheduling Problem

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  2. 【UVA 1380】 A Scheduling Problem &lpar;树形DP&rpar;

    A Scheduling Problem   Description There is a set of jobs, say x1, x2,..., xn <tex2html_verbatim_ ...

  3. UVa 101 The Blocks Problem Vector基本操作

    UVa 101 The Blocks Problem 一道纯模拟题 The Problem The problem is to parse a series of commands that inst ...

  4. UVA - 524 Prime Ring Problem(dfs回溯法)

    UVA - 524 Prime Ring Problem Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & % ...

  5. uva 10837 - A Research Problem&lpar;欧拉功能&plus;暴力&rpar;

    题目链接:uva 10837 - A Research Problem 题目大意:给定一个phin.要求一个最小的n.欧拉函数n等于phin 解题思路:欧拉函数性质有,p为素数的话有phip=p−1; ...

  6. UVA 810 - A Dicey Problem&lpar;BFS)

    UVA 810 - A Dicey Problem 题目链接 题意:一个骰子,给你顶面和前面.在一个起点,每次能移动到周围4格,为-1,或顶面和该位置数字一样,那么问题来了,骰子能不能走一圈回到原地, ...

  7. UVA 10026 Shoemaker&&num;39&semi;s Problem 鞋匠的难题 贪心&plus;排序

    题意:鞋匠一口气接到了不少生意,但是做鞋需要时间,鞋匠只能一双一双地做,根据协议每笔生意如果拖延了要罚钱. 给出每笔生意需要的天数和每天的罚钱数,求出最小罚钱的排列顺序. 只要按罚款/天数去从大到小排 ...

  8. UVA 1640 The Counting Problem UVA1640 求&lbrack;a&comma;b&rsqb;或者&lbrack;b&comma;a&rsqb;区间内0~9在里面各个数的数位上出现的总次数。

    /** 题目:UVA 1640 The Counting Problem UVA1640 链接:https://vjudge.net/problem/UVA-1640 题意:求[a,b]或者[b,a] ...

  9. Uva 101 -- the block problem

    Uva 101 the block problem 题目大意: 输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置.现对这些木块进行操作,操作分为四种. 1.move a o ...

随机推荐

  1. Install Atom editor in ubuntu 14&period;04

    Step 1: Add repository sudo add-apt-repository ppa:webupd8team/atom Step 2: Update the repository su ...

  2. uart启示2&lowbar;异步操作的bug

    发现代码中的隐藏bug真的是一件令人振奋的事情,当然也会疲倦那么一下午! 这个bug只有在一种在一个2604计数周期的一种情况下发生,所以即使是大量的仿真,未必也会发现的了,只有在以后的设计过程中,遇 ...

  3. Mockito自定义verify参数Matcher

    在TDD开发中,也许我们会遇见对一些重要的无返回值的行为测试,比如在用户的积分DB中增加用户的积分,这个行为对于我们的业务具有重要的价值,所以我们也希望能测试覆盖这部分业务价值.这个时候我们就得使用m ...

  4. 在Windows 10上安装Oracle 11g数据库出现的问题及解决

    在Windows 10上安装Oracle 11g数据库,并且很多次出现过:当安装的进度条进行到快要结束的时候弹出一个提示框.如下: [Java(TM)2 Platform Standard Editi ...

  5. js捕获回车事件,并且获取每一条输入内容

    <body> <div style="width: 200px; height: 20px;"> <textarea id="inputVa ...

  6. 关于C&num;控制台传递参数和接收参数

    前言: 写了这么久程序,今天才知道的一个基础知识点,就是程序入口 static void Main(string[] args) 里的args参数是什么意思 ?惭愧... 需求: 点击一个button ...

  7. 【C&sol;C&plus;&plus;多线程编程之六】pthread相互排斥量

    多线程编程之线程同步相互排斥量       Pthread是 POSIX threads 的简称,是POSIX的线程标准.          Pthread线程同步指多个线程协调地,有序地同步使用共享 ...

  8. 关于VNC黑屏的问题

    注意: 1.vncserver启动后生成的ID号(1,2,3)要和VNCview里面填入的 ip:ID要保持一致  不然看到的就是黑屏 比如:vncserver启动后 产生: localhost.lo ...

  9. Signal &lpar;&rpar;函数详细介绍 Linux函数

    http://blog.csdn.net/ta893115871/article/details/7475095 Signal ()函数详细介绍 Linux函数 signal()函数理解 在<s ...

  10. sql 事务日志传输

    原文:sql 事务日志传输 概述 可以使用日志传送将事务日志不间断地从一个数据库(主数据库)发送到另一个数据库(辅助数据库).不间断地备份主数据库中的事务日志,然后将它们复制并还原到辅助数据库,这将使 ...