/*
*题目大意:
*        在数学里面有两种关系,一种是充分条件,即对于集合p,q,p => q,
*        另一种是等价关系,p => q && q =>p, 这两种关系都具有传递性,p
*        => q 可以对应到有节点p到节点q有一条边。问:给定一些集合的充分
*        性关系,确定出若让所有集合都等价,还需在添加最少的充分性条件。
*解题思路:
*        有向图加最少边变强连通,模板题
*/
View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 
  6 const int MAXN = 20005;
  7 
  8 typedef struct _node
  9 {
 10     int v, next;
 11 }N;
 12 N edge[MAXN * 3];
 13 int dfn[MAXN], low[MAXN], step;
 14 int inS[MAXN], id[MAXN], scc, myS[MAXN], top;
 15 int in[MAXN], out[MAXN], cntEdge, head[MAXN];
 16 
 17 void init()
 18 {
 19     cntEdge = step = scc = top = 0;
 20     for(int i = 0; i < MAXN; i++)
 21     {
 22         head[i] = -1;
 23         dfn[i] = low[i] = -1;
 24         id[i] = -1;
 25         in[i] = out[i] = 0;
 26         inS[i] = 0;
 27     }
 28 }
 29 
 30 void tarjan(int n)
 31 {
 32     dfn[n] = low[n] = ++step;
 33     myS[top++] = n;
 34     inS[n] = 1;
 35     for(int f = head[n]; f != -1; f = edge[f].next)
 36     {
 37         int son = edge[f].v;
 38         if(dfn[son] == -1)
 39         {
 40             tarjan(son);
 41             low[n] = min(low[n], low[son]);
 42         }
 43         else if(inS[son] != 0)
 44             low[n] = min(low[n], dfn[son]);
 45     }
 46 
 47     if(low[n] == dfn[n])
 48     {
 49         int tmp;
 50         do
 51         {
 52             tmp = myS[--top];
 53             inS[tmp] = 0;
 54             id[tmp] = scc;
 55         }while(myS[top] != n);
 56         scc++;
 57     }
 58 }
 59 
 60 void addEdge(int u, int v)
 61 {
 62     edge[cntEdge].v = v;
 63     edge[cntEdge].next = head[u];
 64     head[u] = cntEdge++;
 65 }
 66 
 67 
 68 
 69 int main(void)
 70 {
 71 #ifndef ONLINE_JUDGE 
 72     freopen("inHDU2767.txt", "r", stdin);
 73 #endif
 74 
 75     int n, m, cas;
 76     scanf("%d", &cas);
 77     while(cas--)
 78     {
 79         scanf("%d %d", &n, &m);
 80         init();
 81         int u, v;
 82         for(int i = 0; i < m; i++)
 83         {
 84             scanf("%d %d", &u, &v);
 85             addEdge(u, v);
 86         }
 87 
 88         for(int i = 1; i <= n; i++)
 89         {
 90             if(dfn[i] == -1)
 91                 tarjan(i);
 92         }
 93         for(int i = 1; i <= n; i++)
 94         {
 95             for(int j = head[i]; j != -1; j = edge[j].next)
 96             {
 97                 u = i, v = edge[j].v;
 98                 if(id[u] == id[v])
 99                     continue;
100                 else
101                 {
102                     in[id[v]]++;
103                     out[id[u]]++;
104                 }
105             }    
106         }
107         int inNum = 0, outNum = 0;
108         for(int i = 0; i < scc; i++)
109         {
110             if(!in[i])
111                 inNum++;
112             if(!out[i])
113                 outNum++;
114         }
115         if(scc >= 2)
116             printf("%d\n", max(inNum, outNum));
117         else
118             printf("0\n");
119     }
120     return 0;
121 }
posted on 2012-08-16 08:34  cchun  阅读(209)  评论(0编辑  收藏  举报