POJ1236----tarjan缩点

来源:互联网 发布:最高人民法院网络拍卖 编辑:程序博客网 时间:2024/05/16 18:10

题目

一些学校通过网络连接在一起,每个学校手中有一份名单,即它所指向的点。学校A的名单中有学校B,并不能保证学校B的名单里有学校A。

现在有一软件。 
1.问至少发给几个学校才能保证所有的学校都可以得到该软件。 
2.至少加几条边才能使将软件发给任何一个学校后,其他所有学校都可以得到软件。 
N<=100000 

题解

一个有向图,第一问的实质是询问入度为0的点有多少,第二问的可将所有出度/入度为0的点完全相连,因为强联通分量中任意的两点互达,所以需要先对图进行缩点操作。

代码

#include<cstdio>#include<algorithm>#include<cstring>#include<cstdlib>#include<iostream>using namespace std;struct Edge {int from, to, d;Edge *Next;}edge[10010], *First[10010];int n, m;int DFN[10010], LOW[10010];bool instack[10010];int s[10010], Stop;int in_0, out_0;int Dindex, Belong[10010], Bcnt;int in_Edge[10010], out_Edge[10010];void tarjan(int i) {DFN[i] = LOW[i] = ++Dindex;s[++Stop] = i;instack[i] = true;for(Edge *e = First[i]; e; e = e->Next) {int j = e->to;if(!DFN[j]) {tarjan(j);LOW[i] = min(LOW[i], LOW[j]);} else if(instack[j]){LOW[i] = min(LOW[i], DFN[j]);}}if(DFN[i] == LOW[i]) {Bcnt++; int j;do {j = s[Stop--];Belong[j] = Bcnt;instack[j] = false;} while(j != i);}}void solve() {memset(instack, 0, sizeof(instack));memset(DFN, 0, sizeof(DFN));memset(LOW, 0, sizeof(LOW));for(int i = 1; i <= n; i++) {if(!DFN[i]) tarjan(i);}for(int i = 1; i <= n; i++) for(Edge *e = First[i]; e; e = e->Next) {if(Belong[e->to] != Belong[i]) {out_Edge[Belong[i]]++;in_Edge[Belong[e->to]]++; }}for(int i = 1; i <= Bcnt; i++) {if(!in_Edge[i]) in_0++;if(!out_Edge[i]) out_0++; }}int main() {cin >> n >> m;for(int i = 1; i <= m; i++) {int u, v;cin >> u >> v;edge[i].Next = First[u];edge[i].from = u;edge[i].to = v;First[u] = &edge[i];}solve();int ans = max(in_0, out_0);cout << in_0 << endl << out_0;return 0;}


0 0