zoukankan      html  css  js  c++  java
  • zoj Grouping(强连通+缩点+关键路径)

      题意:

        给你N个人,M条年龄大小的关系,现在打算把这些人分成不同的集合,使得每个集合的任意两个人之间的年龄是不可比的。问你最小的集合数是多少?

      分析:

        首先,假设有一个环,那么这个环中的任意两个点之间都是可比的,并且,和这个环相连的任意一个点或环也和这个环是可比的,因为关系具有传递性。但如果两个点或者环,无法处在同一条路径上,那么这两个点和环就是不可比的。所以,如果我们把这些环--强连通分量缩为一个点。强连通分量的点数就是缩点后的点权。那么缩点后的新图就是一个有向带权无环图,题目就是要求我们求出这个有向带权无环图的关键路径----最长路径。(因为那些较短的路径上的点总可以和较长的路径点和为一点)。

      1 //First Edit Time:    2014-11-25 13:38
      2 //Last Edit Time:    2014-11-25 14:24
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 
      8 #define _clr(x, y) memset(x, y, sizeof (x))
      9 #define Min(x, y) (x < y ? x : y)
     10 #define Max(x, y) (x > y ? x : y)
     11 #define INF 0x3f3f3f3f
     12 #define N  100010
     13 
     14 vector<int> map[N], new_map[N];
     15 int low[N], dfn[N];
     16 int Stack[N], be[N];
     17 bool instack[N];
     18 int dist[N], sum[N];
     19 int top, n, cnt, time;
     20 
     21 void Init()
     22 {
     23     top = time = cnt = 0;
     24     _clr(instack, 0);
     25     _clr(Stack, 0);
     26     _clr(dist, -1);
     27     _clr(low, 0);
     28     _clr(sum, 0);
     29     _clr(dfn, 0);
     30     _clr(be, 0);
     31     for(int i=0; i<=n; i++)
     32     {
     33         map[i].clear();
     34         new_map[i].clear();
     35     }
     36 }
     37 
     38 //dfs生成树求强连通分量
     39 void dfs(int u)
     40 {
     41     dfn[u] = low[u] = ++time;
     42     Stack[top++] = u;
     43     instack[u] = true;
     44     for(int i=0; i<(int)map[u].size(); i++)
     45     {
     46         int v = map[u][i];
     47         if(!dfn[v])
     48         {
     49             dfs(v);
     50             low[u] = Min(low[u], low[v]);
     51         }
     52         else if(instack[v])
     53             low[u] = Min(low[u], dfn[v]);
     54     }
     55     if(dfn[u]==low[u])
     56     {
     57         cnt++;
     58         do
     59         {
     60             u = Stack[--top];
     61             instack[u] = false;
     62             be[u] = cnt;
     63             sum[cnt]++;
     64         }while(dfn[u] != low[u]);
     65     }
     66 }
     67 
     68 void Tarjan_Scc()
     69 {
     70     for(int i=1; i<=n; i++)
     71     {
     72         if(!dfn[i])
     73             dfs(i);
     74     }
     75     for(int i=1; i<=n; i++)
     76     {
     77         for(int j=0; j<(int)map[i].size(); j++)
     78         {
     79             int v = map[i][j];
     80             if(be[i] != be[v])
     81                 new_map[be[i]].push_back(be[v]);
     82         }
     83     }
     84 }
     85 
     86 int Get(int u)
     87 {
     88     if(dist[u]!=-1) return dist[u];
     89     dist[u] = 0;
     90     for(int i=0; i<(int)new_map[u].size(); i++)
     91         dist[u] = Max(Get(new_map[u][i]), dist[u]);
     92     return dist[u] = dist[u] + sum[u];
     93 }
     94 
     95 int main()
     96 {
     97     int m, x, y;
     98     while(~scanf("%d%d",&n,&m))
     99     {
    100         Init();
    101         for(int i=0; i<m; i++)
    102         {
    103             scanf("%d%d",&x, &y);
    104             map[x].push_back(y);
    105         }
    106 
    107         Tarjan_Scc();       //Tarjan算法求强连通缩点为一个DAG
    108 
    109         int ans = -INF;
    110         for(int i=1; i<=cnt; i++)   //记忆化搜索求DAG关键路径
    111            ans = Max(Get(i), ans);
    112 
    113         printf("%d
    ", ans);
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    接口测试断言详解(Jmeter)
    接口测试参数化详解(Jmeter)
    记一次线上内存泄漏问题的排查过程
    BI入门经典(转载)
    图形初阶
    数据的输入
    来自 Google 的 R 语言编码风格指南
    提醒程序员注意的一些事项--R
    R语言-attach、detach、with
    R数据类型
  • 原文地址:https://www.cnblogs.com/khan724/p/4121061.html
Copyright © 2011-2022 走看看