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 }