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:
这两句话是不一样的,在有向图中存在非环边还是非桥的情况