loj 1034(最小点基)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25911

思路:强连通缩点,在新图中找入度为0的点的个数即可。

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<iostream>

  5 #include<cstdio>

  6 #include<cstring>

  7 #include<cstdlib>

  8 #include<cmath>

  9 #include<climits>

 10 #include<algorithm>

 11 #include<stack>

 12 #include<map>

 13 #include<set>

 14 #include<vector>

 15 #include<queue>

 16 #include<list>

 17 using namespace std;

 18 #define MAXN 11111

 19 #define inf 1<<30

 20 #define INF 1LL<<60

 21 #define FILL(a,b) memset(a,b,sizeof(a))

 22 typedef long long ll;

 23 typedef unsigned long long llu;

 24 typedef pair<int,int>PP;

 25 template<class T> inline T Get_MIN(const T &a,const T &b){ return a < b ? a : b; }

 26 template<class T> inline T Get_MAX(const T &a,const T &b){ return a > b ? a : b; }

 27 template<class T> inline T ABS(const T &a){ return a < 0 ? -a : a; }

 28 

 29 struct Edge{

 30     int v,next;

 31 }edge[MAXN*20];

 32 

 33 int n,m,NE;

 34 int head[MAXN];

 35 

 36 void Insert(int u,int v)

 37 {

 38     edge[NE].v=v;

 39     edge[NE].next=head[u];

 40     head[u]=NE++;

 41 }

 42 

 43 int low[MAXN],dfn[MAXN],color[MAXN];

 44 bool mark[MAXN];

 45 int scc_count,cnt;

 46 stack<int>S;

 47 void Tarjan(int u)

 48 {

 49     low[u]=dfn[u]=++cnt;

 50     mark[u]=true;

 51     S.push(u);

 52     for(int i=head[u];i!=-1;i=edge[i].next){

 53         int v=edge[i].v;

 54         if(dfn[v]==0){

 55             Tarjan(v);

 56             low[u]=Get_MIN(low[u],low[v]);

 57         }else if(mark[v]){

 58             low[u]=Get_MIN(low[u],dfn[v]);

 59         }

 60     }

 61     if(low[u]==dfn[u]){

 62         scc_count++;

 63         int v;

 64         do{

 65             v=S.top();

 66             S.pop();

 67             mark[v]=false;

 68             color[v]=scc_count;

 69         }while(u!=v);

 70     }

 71 }

 72 

 73 int degree[MAXN];

 74 

 75 int main()

 76 {

 77     int _case,u,v,ans,t=1;

 78     scanf("%d",&_case);

 79     while(_case--){

 80         scanf("%d%d",&n,&m);

 81         NE=0;

 82         FILL(head,-1);

 83         FILL(dfn,0);

 84         FILL(mark,false);

 85         cnt=scc_count=0;

 86         while(m--){

 87             scanf("%d%d",&u,&v);

 88             Insert(u,v);

 89         }

 90         for(int i=1;i<=n;i++)if(dfn[i]==0)Tarjan(i);

 91         FILL(degree,0);

 92         for(int u=1;u<=n;u++){

 93             for(int i=head[u];i!=-1;i=edge[i].next){

 94                 int v=edge[i].v;

 95                 if(color[u]!=color[v]){

 96                     degree[color[v]]++;

 97                 }

 98             }

 99         }

100         ans=0;

101         for(int i=1;i<=scc_count;i++)if(degree[i]==0)ans++;

102         printf("Case %d: %d\n",t++,ans);

103     }

104     return 0;

105 }
View Code

 

你可能感兴趣的:(OJ)