LightOJ-1034-tarjan

来源:互联网 发布:在线app打包网站源码 编辑:程序博客网 时间:2024/06/05 15:04

题目大意:有n个灯,需要把他们都点亮,接下来有m行u,v表示u点亮后,v也随之被点亮,问最少需要点亮几盏灯;

题目解析:tarjan先把所有强连通分量求出来,map[i]表示第i个点在第几个强连通分量中,然后我们需要dfs每个强连通分量,如果发现map[u]!=map[v],也就是说两个强连通分量之间有一条边,那么令一边的就可以舍去,因为我们总可以在map[u]所在的分量中到达另一个分量的任意一条边;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<vector>#include<stack>using namespace std;const int MAX=10010;vector<int>vec[MAX];int map[MAX],dfn[MAX],low[MAX],tot[MAX],depth,scc,ans,n,m;stack<int>s;void init(){int i;depth=scc=ans=0;for(i=0;i<MAX;i++)vec[i].clear();memset(map,-1,sizeof(map));memset(tot,0,sizeof(tot));memset(low,0,sizeof(low));memset(dfn,-1,sizeof(dfn));}void tarjan(int u){int i;dfn[u]=low[u]=depth++;s.push(u);for(i=0;i<vec[u].size();i++){int v=vec[u][i];if(dfn[v]==-1){tarjan(v);low[u]=min(low[u],low[v]);}else if(map[v]==-1)low[u]=min(low[u],dfn[v]);}if(low[u]==dfn[u]){int v;do{             v = s.top();             map[v] = scc;             s.pop();          }while(v!=u);          scc++;  }}void dfs(int u){int i,v;dfn[u]=1;for(i=0;i<vec[u].size();i++){v=vec[u][i];if(map[u]!=map[v])tot[map[v]]++;if(!dfn[v])dfs(v);}}int main(){int cas,c,i,u,v;scanf("%d",&cas);for(c=1;c<=cas;c++){init();scanf("%d%d",&n,&m);for(i=0;i<m;i++){scanf("%d%d",&u,&v);u--;v--;vec[u].push_back(v);}for(i=0;i<n;i++)if(dfn[i]==-1)tarjan(i);memset(dfn,0,sizeof(dfn));for(i=0;i<n;i++)if(!dfn[i])dfs(i);for(i=0;i<scc;i++){if(!tot[i])ans++;}printf("Case %d: %d\n",c,ans);}return 0;}


0 0
原创粉丝点击