题意:

     给你一个有向图,问你这个图是不是单连通图,单连通就是任意两点之间至少存在一条可达路径。

思路:

     先强连通所点,重新建图,此时的图不存在环,然后我们在看看是否存在一条路径可以吧所有点都覆盖了就行了,直接一遍拓扑排序,只要拓扑排序唯一就行了,拓扑排序唯一的条件是 每次最多只能有一个进队。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<map> #define N_node 1005
#define N_edge 6500
#define INF 1000000000 using namespace std; typedef struct
{
int to ,next;
}STAR; typedef struct
{
int a ,b;
}EDGE; STAR E[N_edge] ,E1[N_edge] ,E2[N_edge];
EDGE edge[N_edge];
map<int ,map<int ,int> >mk_map;
stack<int>sk;
int list[N_node] ,list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,cnt;
int in[N_node] ,out[N_node];
int mark[N_node]; void add(int a ,int b)
{
E1[++tot].to = b;
E1[tot].next = list1[a];
list1[a] = tot; E2[tot].to = a;
E2[tot].next = list2[b];
list2[b] = tot;
} void _add(int a ,int b)
{
E[++tot].to = b;
E[tot].next = list[a];
list[a] = tot;
} void DFS_1(int s)
{
mark[s] = 1;
for(int k = list1[s] ;k ;k = E1[k].next)
{
int xin = E1[k].to;
if(!mark[xin])
DFS_1(xin);
}
sk.push(s);
} void DFS_2(int s)
{
mark[s] = 1;
Belong[s] = cnt;
for(int k = list2[s] ;k ;k = E2[k].next)
{
int xin = E2[k].to;
if(!mark[xin])
DFS_2(xin);
}
} bool TP_sort(int n)
{
queue<int>q;
int ss = 0;
for(int i = 1 ;i <= n ;i ++)
{
if(in[i] == 0)
{
q.push(i);
ss ++;
if(ss > 1) return 0;
}
}
int sot = 0;
while(!q.empty())
{
int xin ,tou;
tou = q.front();
q.pop();
sot ++;
ss = 0;
for(int k = list[tou] ;k ;k = E[k].next)
{
xin = E[k].to;
if(--in[xin] == 0)
{
ss ++;
q.push(xin);
if(ss > 1) return 0;
}
}
}
return sot == n;
} int main ()
{
int t ,n ,m;
int a ,b ,i;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
memset(list1 ,0 ,sizeof(list1));
memset(list2 ,0 ,sizeof(list2));
tot = 1;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d" ,&a ,&b);
add(a ,b);
edge[i].a = a ,edge[i].b = b;
}
memset(mark ,0 ,sizeof(mark));
while(!sk.empty())sk.pop();
for(int i = 1 ;i <= n ;i ++)
if(!mark[i]) DFS_1(i);
cnt = 0;
memset(mark ,0 ,sizeof(mark));
while(!sk.empty())
{
int xin = sk.top();
sk.pop();
if(mark[xin]) continue;
cnt ++;
DFS_2(xin);
}
mk_map.clear();
memset(in ,0 ,sizeof(in));
memset(out ,0 ,sizeof(out));
memset(list ,0 ,sizeof(list));
tot = 1; for(i = 1 ;i <= m ;i ++)
{
a = Belong[edge[i].a];
b = Belong[edge[i].b];
if(a == b || mk_map[a][b]) continue;
mk_map[a][b] = 1;
in[b] ++ ,out[a] ++;
_add(a ,b);
}
if(TP_sort(cnt)) puts("Yes");
else puts("No");
}
return 0;
}


最新文章

  1. 你的日志组件记录够清晰嘛?--自己开发日志组件 Logger
  2. DNS知识指南
  3. jquery实现tab切换完整代码
  4. ssh相关操作
  5. Debian字符模式下修改显示分辨率
  6. [转]Oracle快速入门
  7. 怎么用jq封装插件
  8. Directx3d绘制包围体并控制光照效果
  9. python爬虫解决gbk乱码问题
  10. MySQL 基础知识梳理学习(三)----InnoDB日志相关的几个要点
  11. Data Science Project
  12. [复现]蝉知cms 5.6 前台注入
  13. react 子元素修改父元素值的一个偏方,虽然简单,但是不建议用,
  14. javanio1----传统io
  15. Delphi 7调用C语言编写的DLL
  16. opencv的基本数据类型CvPoint,CvSize,CvRect,CvScalar
  17. 011PHP文件处理——文件处理 文件内容分页操作类
  18. NAT 穿透
  19. Cannot sending data from mongodb into elasticsearch using logstash
  20. 我把阿里云centos gcc从4.4.7升级到4.8.2的经历

热门文章

  1. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 + 二叉排序树 + 最近公共祖先
  2. 聊一聊和Nacos 2.0.0对接那些事
  3. for-in 语句
  4. vim命令c编程
  5. The 2018 ACM-ICPC CCPC NING XIA G-Factories
  6. Mysql之索引选择及优化
  7. (一)SpringBoot启动过程的分析-启动流程概览
  8. 「HTML+CSS」--自定义按钮样式【003】
  9. java例题_08 输入特定数字求和(n个a位数递增求和问题)
  10. 使用 Android Studio 开发 widget 安卓桌面插件