题目链接:http://poj.org/problem?id=2762

题意是 有t组样例,n个点m条有向边,取任意两个点u和v,问u能不能到v 或者v能不能到u,要是可以就输出Yes,否则输出No。注意一点,条件是或者!所以不是判断双连通图的问题。

我一开始没看到'or'这个条件,所以直接tarjan判断是否只有一个强连通分量,果断WA。

所以需要给原图缩点,用tarjan把图变成一个有向无环图,要是只有一个scc,那就直接输出Yes。那接下来讨论多个scc,要是新图中有两个及以上的点的入度为0,则这些点都不能相互到达,所以输出No,所以我们找到唯一一个入度为0的点作为root,然后从这个点来拓扑排序,出队入队的过程肯定是一进一出的,所以根据过程来判断是否输出Yes和No。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int MAXN = ;
struct data {
int next , to;
}edge[MAXN * ];
int head[MAXN] , st[MAXN] , low[MAXN] , dfn[MAXN] , block[MAXN] , du[MAXN];
int top , ord , sccnum , cont;
bool instack[MAXN];
vector <int> G[MAXN]; inline void add(int u , int v) {
edge[cont].next = head[u];
edge[cont].to = v;
head[u] = cont++;
} void init() {
memset(head , - , sizeof(head));
memset(dfn , , sizeof(dfn));
memset(du , , sizeof(du));
memset(instack , false , sizeof(instack));
top = sccnum = ord = cont = ;
} void tarjan(int u) {
low[u] = dfn[u] = ++ord;
st[++top] = u;
instack[u] = true;
for(int i = head[u] ; ~i ; i = edge[i].next) {
int v = edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u] , low[v]);
}
else if(instack[v]) {
low[u] = min(low[u] , low[v]);
}
}
if(low[u] == dfn[u]) {
int v;
sccnum++;
do {
v = st[top--];
instack[v] = false;
block[v] = sccnum;
}while(u != v);
}
} void top_sort() {
queue <int> que;
while(!que.empty()) {
que.pop();
}
cont = ;
for(int i = ; i <= sccnum ; i++) {
if(!du[i]) {
que.push(i);
cont++;
}
}
if(cont > ) {
printf("No\n");
return ;
}
while(!que.empty()) {
int temp = que.front() , cnt = ;
que.pop();
for(int i = ; i < G[temp].size() ; i++) {
du[G[temp][i]]--;
if(!du[G[temp][i]]) {
cnt++;
cont++;
que.push(G[temp][i]);
}
}
if(cnt > ) {
printf("No\n");
return ;
}
}
if(cont != sccnum) {
printf("No\n");
}
else {
printf("Yes\n");
}
} int main()
{
int t , n , m , u , v;
scanf("%d" , &t);
while(t--) {
scanf("%d %d" , &n , &m);
init();
for(int i = ; i < m ; i++) {
scanf("%d %d" , &u , &v);
add(u , v);
}
for(int i = ; i <= n ; i++) {
G[i].clear();
if(!dfn[i])
tarjan(i);
}
if(sccnum == ) {
printf("Yes\n");
continue;
}
for(int u = ; u <= n ; u++) {
for(int i = head[u] ; ~i ; i = edge[i].next) {
int v = edge[i].to;
if(block[u] != block[v]) {
du[block[v]]++;
G[block[u]].push_back(block[v]);
}
}
}
top_sort();
}
}

最新文章

  1. tensorflow安装日志(PIP)
  2. [转] 多进程下数据库环境的恢复:DB_REGISTER
  3. android播放器如何获取音乐文件信息
  4. 二模 (5)day1
  5. 【NOIP2013】【P1441】花匠
  6. jquery下拉框实现将左边的选项添加到右边区域
  7. Mip-Mapping很重要
  8. 【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)
  9. homework01
  10. node.js + socket.io实现聊天室一
  11. SQL Server 创建全文索引
  12. POJ 3928 &amp;amp; HDU 2492 Ping pong(树阵评价倒数)
  13. 安装阿里Java代码规约插件
  14. Unity3D学习笔记(五)C#与JavaScript组件访问的比较
  15. oracle追加表空间
  16. 福州大学软件工程1816 | W班 第6次作业WordCount成绩排名
  17. ASP.NET EF 延迟加载,导航属性延迟加载
  18. linux 乌班图 安装pycharm
  19. isspace 对含有中文 的字符串进行检查的时候表现不正常!?
  20. 用 javascript 实现 ping 一个主机,仅测试是否能够连接。

热门文章

  1. trackr: An AngularJS app with a Java 8 backend – Part I
  2. 在oracle中where 子句和having子句中的区别
  3. 安卓自动化测试工具MonkeyRunner之使用ID进行参数化,以及List选择某项和弹出框点击确定的写法
  4. Qt之启动外部程序
  5. UVa 10129 (并查集 + 欧拉路径) Play on Words
  6. Samba 4.x.x全版本存在命令执行漏洞
  7. AngularJS promise()
  8. Go2Shell 打开设置窗口
  9. PL/Sql 中创建、调试、调用存储过程
  10. [Everyday Mathematics]20150125