zoukankan      html  css  js  c++  java
  • poj 1236 Network of Schools : 求需要添加多少条边成为强连通图 tarjan O(E)

      1 /**
      2 problem: http://poj.org/problem?id=1236
      3 
      4 缩点后入度为0的点的总数为需要发放软件的学校个数
      5 缩点后出度为0的点的总数和入度为0的点的总数的最大值为需要增加的传输线路的条数(头尾相接)
      6 特别的,当图为强连通图时,发放软件的学校个数为1, 增加线路为0
      7 **/
      8 #include<stdio.h>
      9 #include<stack>
     10 #include<algorithm>
     11 using namespace std;
     12 
     13 class Graphics{
     14     const static int MAXN = 105;
     15     const static int MAXM = 100005;
     16 private:
     17     struct Edge{
     18         int to, next;
     19         bool bridge;
     20     }edge[MAXM];
     21     struct Point{
     22         int dfn, low, color;
     23     }point[MAXN];
     24     int sign, dfnNum, colorNum, sumOfPoint, first[MAXN];
     25     bool vis[MAXN];
     26     stack<int> stk;
     27     void tarjan(int u){
     28         point[u].dfn = ++dfnNum;
     29         point[u].low = dfnNum;
     30         vis[u] = true;
     31         stk.push(u);
     32         for(int i = first[u]; i != -1; i = edge[i].next){
     33             int to = edge[i].to;
     34             if(!point[to].dfn){
     35                 tarjan(to);
     36                 point[u].low = min(point[to].low, point[u].low);
     37                 if(point[to].low > point[u].dfn){
     38                     edge[i].bridge = true;
     39                 }
     40             }else if(vis[to]){
     41                 point[u].low = min(point[to].dfn, point[u].low);
     42             }
     43         }
     44         if(point[u].dfn == point[u].low){
     45             vis[u] = false;
     46             point[u].color = ++colorNum;
     47             while(stk.top() != u){
     48                 vis[stk.top()] = false;
     49                 point[stk.top()].color = colorNum;
     50                 stk.pop();
     51             }
     52             stk.pop();
     53         }
     54     }
     55 public:
     56     void clear(int n){
     57         sign = dfnNum = colorNum = 0;
     58         for(int i = 1; i <= n; i ++){
     59             first[i] = -1;
     60             vis[i] = 0;
     61         }
     62         sumOfPoint = n;
     63         while(!stk.empty()) stk.pop();
     64     }
     65     void addEdgeOneWay(int u, int v){
     66         edge[sign].to = v;
     67         edge[sign].bridge = false;
     68         edge[sign].next = first[u];
     69         first[u] = sign ++;
     70     }
     71     void addEdgeTwoWay(int u, int v){
     72         addEdgeOneWay(u, v);
     73         addEdgeOneWay(v, u);
     74     }
     75     void tarjanAllPoint(){
     76         for(int i = 1; i <= sumOfPoint; i ++){
     77             if(!point[i].dfn)
     78                 tarjan(i);
     79         }
     80     }
     81     pair<int, int> getAns(){
     82         int ans = 0, ans2 = 0;
     83         int *indegree = new int[sumOfPoint+1];
     84         int *outdegree = new int[sumOfPoint+1];
     85         for(int i = 1; i <= sumOfPoint; i ++){
     86             indegree[i] = 0;
     87             outdegree[i] = 0;
     88         }
     89         tarjanAllPoint();
     90         for(int i = 1; i <= sumOfPoint; i ++){
     91             for(int j = first[i]; j != -1; j = edge[j].next){
     92                 int to = edge[j].to;
     93                 if(point[to].color != point[i].color){
     94                     outdegree[point[i].color] ++;
     95                     indegree[point[to].color] ++;
     96                 }
     97             }
     98         }
     99         for(int i = 1; i <= colorNum; i ++){
    100             if(!indegree[i]){
    101                 ans ++;
    102             }
    103             if(!outdegree[i]){
    104                 ans2 ++;
    105             }
    106         }
    107         delete []indegree; delete []outdegree;
    108         if(colorNum == 1){
    109             return make_pair(1, 0);
    110         }else{
    111             return make_pair(ans, max(ans, ans2));
    112         }
    113     }
    114 }graph;
    115 
    116 int main(){
    117     int n;
    118     scanf("%d", &n);
    119     graph.clear(n);
    120     for(int i = 1; i <= n; i ++){
    121         int a;
    122         while(scanf("%d", &a) && a){
    123             graph.addEdgeOneWay(i, a);
    124         }
    125     }
    126     pair<int, int> ans = graph.getAns();
    127     printf("%d
    %d
    ", ans.first, ans.second);
    128     return 0;
    129 }

     ps:

    这两句话是不一样的,在有向图中存在非环边还是非桥的情况

  • 相关阅读:
    查看mysql版本的四种方法及常用命令
    newInstance和new的区别(good)
    Citrix 服务器虚拟化之六 Xenserver虚拟机创建与快照
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 前缀表达式
    Java实现 蓝桥杯 算法训练 前缀表达式
  • 原文地址:https://www.cnblogs.com/DarkScoCu/p/10533860.html
Copyright © 2011-2022 走看看