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\n%d\n", ans.first, ans.second);
128     return 0;
129 }

 ps:

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

posted @ 2019-03-14 22:02  DarkScoCu  阅读(132)  评论(0编辑  收藏  举报