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
",t++,ans);
103     }
104     return 0;
105 }
View Code
原文地址:https://www.cnblogs.com/wally/p/3349757.html