标签:into auto wan ted std receiving ogr positive each
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 19613 | Accepted: 7725 |
Description
Input
Output
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
1 2
Source
思路:求一个有向图从几个点出发可以遍历整个图、以及至少加几条边使整张图强联通。
缩点以后,显然入度为0的点的个数就是第一问的答案。
然后第二问答案显然是入度为0和出度为0的个数的最大值,即出入度为0的点间连条边就可以了。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define ms(a, b) memset(a, b, sizeof(a)) 6 const int N = 101, M = 10001; 7 int h[N], p[M], a[M], fa[N], out[N], in[N], dfn[N], low[N]; 8 int scc, top, ts, cnt, sta[N], insta[N]; 9 void add(int x, int y) { p[++cnt] = h[x]; a[cnt] = y; h[x] = cnt; } 10 11 void tarjan(int u) { 12 int i; 13 dfn[u] = low[u] = ++ts; 14 sta[++top] = u; insta[u] = 1; 15 for (i = h[u]; i; i = p[i]) 16 if (!dfn[a[i]]) { 17 tarjan(a[i]); 18 low[u] = min(low[u], low[a[i]]); 19 } else if (insta[a[i]]) 20 low[u] = min(low[u], dfn[a[i]]); 21 if (dfn[u] == low[u]) { 22 ++scc; 23 do { 24 i = sta[top--]; 25 insta[i] = 0; 26 fa[i] = scc; 27 } while (i != u); 28 } 29 } 30 31 int main() { 32 int i, j, n, m, x, b; 33 34 while (scanf("%d", &n) != EOF) { 35 ms(dfn, 0); ms(out, 0); ms(h, 0); ms(in, 0); 36 ts = cnt = top = scc = 0; 37 for (i = 1; i <= n; ++i) 38 while (scanf("%d", &x) && x) add(i, x); 39 for (i = 1; i <= n; ++i) 40 if (!dfn[i]) tarjan(i); 41 for (i = 1; i <= n; ++i) 42 for (j = h[i]; j; j = p[j]) 43 if (fa[i] != fa[a[j]]) 44 ++out[fa[i]], ++in[fa[a[j]]]; 45 int a1=0,a2=0; 46 for (i = 1; i <= scc; ++i) { 47 if (!out[i]) ++a1; 48 if (!in[i]) ++a2; 49 } 50 if (scc == 1) puts("1\n0"); 51 else printf("%d\n%d\n", a2, max(a1, a2)); 52 } 53 return 0; 54 }
标签:into auto wan ted std receiving ogr positive each
原文地址:http://www.cnblogs.com/mj-liylho/p/7529025.html