/*题意:有向图,求这样的点的数量:所有点都能到达它.缩点成有向无环图,思:如果该强连通有出度,那么
从该出度出去的边必然回不来(已经缩点了),所以有出度的强连通必然不是。那么是不是所有出度为0的强连通
分量都是呢?显然不是,如果存在多个出度为0的强连通,他们必然无解(他们之间必然不连通)。
任然遍历边,判断不在一个连通分量中的边(即为缩点后的边)和点,考察期出度即可。*/
#include<iostream> //329ms,1A,基础题。
#include<vector>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
int n;int m;
const int MAX=10001;
vector<vector<int> >edges(MAX);
int visited[MAX];
int low[MAX];
int dfn[MAX];
bool has_outd[MAX]; //是否有出度
int Strongly_connected_branch[MAX]; //并为一个强连通,标记为1.2.3...
int num;int times;
bool is_popular[MAX]; //整个强连通分支i是否有出度,其中一个点有即有
stack<int>s;
bool instack[MAX];
int num_of_popular; //统计最终数量
void tarjan(int u)
{
low[u]=dfn[u]=times++;
instack[u]=1;
s.push(u);
int len=edges[u].size();
for(int i=0;i<len;i++)
{
int v=edges[u][i];
if(visited[v]==0)
{
visited[v]=1;
tarjan(v);
if(low[u]>low[v])low[u]=low[v];
}
else if(instack[v]&&low[u]>dfn[v]) //有向图,要问是否在栈中,后向边,V为U某个祖先
{
low[u]=dfn[v];
}
}
if(dfn[u]==low[u]) //在一个SCC
{
num++;int temp;
do
{
temp=s.top();
instack[temp]=0;
s.pop();
Strongly_connected_branch[temp]=num;
} while(temp!=u);
}
}
void initialize() //初始化
{
num_of_popular=num=times=0;
for(int i=0;i<=n;i++)
{
has_outd[i]=instack[i]=low[i]=dfn[i]=visited[i]=0;
edges[i].clear();
is_popular[i]=1;
Strongly_connected_branch[i]=-1;
}
}
bool readin()
{
scanf("%d",&n);
scanf("%d",&m);
initialize();
int from,to;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&from,&to);
edges[from].push_back(to);
}
return 1;
}
void solve()
{
for(int i=1;i<=n;i++)
if(visited[i]==0)
{
visited[i]=1;
tarjan(i);
}
for(int i=1;i<=n;i++) //自己思得:枚举所有边,缩点只是把所有SCC分开
{
int len=edges[i].size();
for(int j=0;j<len;j++)
{
int v=edges[i][j];
if(Strongly_connected_branch[v]!=Strongly_connected_branch[i])//不在用一个强连通分支
{
has_outd[i]=1; //i所在强连通分量有出度
is_popular[Strongly_connected_branch[i]]=0; //其所在强连通全跪!
break;
}
}
}
queue<int>q;
for(int i=1;i<=n;i++) //统计期所在强连通出度为0的点
{
if(is_popular[Strongly_connected_branch[i]]==0){continue;}
if(has_outd[i]==0)q.push(i);
}
int te=Strongly_connected_branch[q.front()];
while(!q.empty()) //判断他们是否都在一个强连通中,否则跳出,无解。
{
int cur=q.front();
if(te!=Strongly_connected_branch[cur]){printf("0\n");return;}
num_of_popular++;
q.pop();
te=Strongly_connected_branch[cur];
}
printf("%d\n",num_of_popular);
}
int main()
{
readin();
solve();
return 0;
}

最新文章

  1. 浏览器控制台js代码与后台不同步
  2. 数组,集合分割函数,join()
  3. python成长之路——第一天
  4. const修饰虚函数
  5. Java并发控制机制详解
  6. JAVA classpath, 纠正我一直以来错误的认知
  7. Create screenshots of a web page using Python and QtWebKit | Roland's Blog
  8. 由href return false 来看阻止默认事件
  9. OSPF理论总结
  10. SQL sever 创建定时执行任务
  11. char码值对应列表大全
  12. Javascript高级编程学习笔记(15)—— 引用类型(4)RegExp类型
  13. 性能测试四十一:sql案例之慢sql配置、执行计划和索引
  14. kmp循环节
  15. [py]__name__ 属于哪个文件
  16. 使用JFileChooser实现在指定文件夹下批量添加根据“数字型样式”或“非数字型样式”命令的文件夹
  17. C#读取Excel表中的数据时混合字段部分数据没有
  18. 事件委托,js中的一种优化方法
  19. JDK7,8,JD9的hashmap,hashtable,concurrenthashmap及他们的区别
  20. CentOS7系统更改网卡名为eth0

热门文章

  1. linux下自定义pid实现任意数据采集
  2. java中properties的使用实例
  3. JAVA之NIO按行读取大文件
  4. Web开发者不容错过的10个HTML5工具
  5. 浅析HashSet add() 方法存储自定义类型对象的过程
  6. 汇编4OPCODE
  7. JDK 5 ~ 11 新特性倾情整理
  8. Linux环境下挂载SD卡的教程
  9. [模板] 动态ST表
  10. SQL语句操作SQL SERVER数据库登录名、用户及权限