• uva1380 A Scheduling Problem


    按紫书来
    注意这道题的题目给了很大的方便,就相当于验证k是不是答案,不是的话就是k+1

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<sstream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 200 + 5;
    const int INF = 1000000000;
    
    struct Edge {
      int u, v, d; // d=1 means u->v, d=2 means v->u, d=0 means u-v
      Edge(int u=0, int v=0, int d=0):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 = 0;
      for(int i = 0; i < edges[u].size(); i++) {
        int v = edges[u][i].v;
        if(edges[u][i].d == 1)
          ans = max(ans, dfs(v)+1);
      }
      return ans;
    }
    
    bool read_data() {
      bool have_data = false;
      int a, b;
      n = 0;
      for(int i = 0; i < maxn; i++) edges[i].clear();
      memset(have_father, 0, sizeof(have_father));
    
      while(cin >> a && a){
        string str;
        have_data = true;
        if(a > n) n = a;
        while(cin >> str && str != "0"){          //一组数据
          int len = str.length();
          char dir = str[len-1];
          if(dir == 'd' || dir == 'u') str = str.substr(0, len-1);
          stringstream ss(str);
          ss >> b; // b is a's son
          if(b > n) n = b;
          have_father[b] = 1;
          if(dir == 'd'){
            edges[a].push_back(Edge(a, b, 1)); // forward
            edges[b].push_back(Edge(b, a, 2)); // backward
          }else if(dir == 'u'){
            edges[a].push_back(Edge(a, b, 2));
            edges[b].push_back(Edge(b, a, 1));
          }else{
            edges[a].push_back(Edge(a, b, 0)); // it's a rooted tree, so we don't store edge to father
          }
        }
      }
      if(have_data) {
        for(int i = 1; i <= n; i++)
          if(!have_father[i]) { root = i; break; }  //找一个root  //if(!have_father[i] && !edges[i].empty())
      }
      return have_data;
    }
    
    struct UndirectedSon {
      int w, f, g;
      UndirectedSon(int w=0, int f=0, int g=0):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] = 0;
        return true;
      }
      vector<UndirectedSon> sons;
      int f0 = 0, g0 = 0; // 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 = 0; k < edges[i].size(); k++) {
        int w = edges[i][k].v;
        if(w == fa) continue;
        dp(w, i);
        int d = edges[i][k].d;
        if(d == 0) sons.push_back(UndirectedSon(w, f[w], g[w]));
        else if(d == 1) g0 = max(g0, g[w]+1);
        else f0 = max(f0, f[w]+1);
      }
      // 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, ...}   //按f从小到大排
      maxg[s-1] = sons[s-1].g;
      for(int k = s-2; k >= 0; k--)
        maxg[k] = max(sons[k].g, maxg[k+1]);    //记录k之后最长的g[w],用于排序
      for(int p = 0; p <= sons.size(); p++) {
        int ff = f0, gg = g0;                             //原来最长的有向边
        if(p > 0) ff = max(ff, sons[p-1].f+1);
        if(p < sons.size()) gg = max(gg, maxg[p]+1);
        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-1] = sons[s-1].f;
      for(int k = s-2; k >= 0; k--)
        maxf[k] = max(sons[k].f, maxf[k+1]);
      for(int p = 0; p <= sons.size(); p++) {
        int ff = f0, gg = g0;
        if(p > 0) gg = max(gg, sons[p-1].g+1);   //比p小的f(w)变成w->i,不会让f[i]变大,但可能让g[i]变小
        if(p < sons.size()) ff = max(ff, maxf[p]+1);
        if(ff + gg <= maxlen) g[i] = min(g[i], gg);
      }
    
      return f[i] < INF;
    }
    
    int main() {
      while(read_data()) {
        maxlen = 0;
        for(int i = 1; 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, -1)) cout << maxlen+1 << "
    ";
        else cout << maxlen+2 << "
    ";
      }
      return 0;
    }
  • 相关阅读:
    计算器修正代码
    AsEnumrable和AsQueryable的区别
    c# 解释器模式与sping.net表达式的结合应用(金融里经常需要用到公式,这个公式是抽象的需要自己解释)
    Spring.net 间接调用被AOP拦截的方法失效(无法进入aop的拦截方法)
    信息熵公式的由来(转)
    期望风险、经验风险与结构风险之间的关系(转)
    梯度(转)
    奇特的数学问题(转)
    最大似然估计和最大后验估计(转)
    贝叶斯思想以及与最大似然估计、最大后验估计的区别(转)
  • 原文地址:https://www.cnblogs.com/lqerio/p/9800713.html
Copyright © 2020-2023  润新知