题目链接:http://codeforces.com/contest/652/problem/E

给你n个点m个边,x和y双向连接,要是z是1表示这条边上有宝藏,0则没有,最后给你起点和终点,问你要是到从起点到终点要是中间遇到宝藏就输出YES,否则就输出NO。

每条边只能经过一次,而且这个图保证连通的。

我用tarjan强连通缩点,把这个图变成一棵树,要是起点终点在一个连通分量里且分量里的边有宝藏,那么就输出YES。否则,就找起点到终点直接的路有没有宝藏,因为缩点之后是一棵树,所以起点和终点只有一条路。那我从起点dfs一遍,par[i]记录的是i前驱节点。那我之后就从终点反向遍历这条路,要是路上有宝藏,就输出YES。

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
using namespace std;
const int MAXN = 3e5 + ;
typedef pair <int , int> P;
struct data {
int next , to , art;
}edge[MAXN * ];
int head[MAXN] , low[MAXN] , dfn[MAXN] , st[MAXN] , block[MAXN] , p[MAXN];
int top , ord , sccnum , end_point , cont;
bool instack[MAXN] , vis[MAXN] , ok , res;
vector <P> G[MAXN]; void init() {
memset(head , - , sizeof(head));
} inline void add(int u , int v , int art) {
edge[cont].next = head[u];
edge[cont].to = v;
edge[cont].art = art;
head[u] = cont++;
} void tarjan(int u , int par) {
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(v == par)
continue;
if(!dfn[v]) {
tarjan(v , u);
low[u] = min(low[v] , low[u]);
}
else if(instack[v]) {
low[u] = min(low[u] , dfn[v]);
}
}
if(dfn[u] == low[u]) {
sccnum++;
int v;
do {
v = st[top--];
instack[v] = false;
block[v] = sccnum;
}while(u != v);
}
} void dfs(int u , int par) {
p[u] = par;
for(int i = ; i < G[u].size() ; i++) {
int v = G[u][i].first;
if(par == v)
continue;
if(G[u][i].second)
vis[v] = true;
dfs(v , u);
}
} int main()
{
int n , m , u , v , art , s , e , heheda = ;
scanf("%d %d" , &n , &m);
init();
for(int i = ; i < m ; i++) {
scanf("%d %d %d" , &u , &v , &art);
add(u , v , art);
add(v , u , art);
if(art == )
heheda = ;
}
scanf("%d %d" , &s , &e);
if(heheda) {
printf("NO\n");
return ;
}
tarjan( , -);
end_point = block[e];
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]) {
G[block[u]].push_back(P(block[v] , edge[i].art));
}
else {
if(!vis[block[u]])
vis[block[u]] = (bool)(edge[i].art);
}
}
}
if(block[s] == end_point && vis[block[s]]) {
printf("YES\n");
return ;
}
if(vis[block[s]])
res = true;
dfs(block[s] , -);
for(int i = end_point ; ~i ; i = p[i]) {
if(vis[i])
res = true;
}
if(res)
printf("YES\n");
else
printf("NO\n");
}

最新文章

  1. Minor【 PHP框架】6.代理
  2. Matrix
  3. linux用终端上传文件和文件家到远程的服务器
  4. :root
  5. Linux平台下线程池的原理及实现
  6. Hibernate 错误处理
  7. 项目中添加Log4J支持
  8. HDU 1695 (莫比乌斯反演) GCD
  9. 关于UITableViewCell的循环利用--面向初学者
  10. 13 java 设计模式--单例模式
  11. SPOJ 7258 Lexicographical Substring Search(后缀自动机)
  12. MySQL DBA成长之路
  13. [转]从命令行往 iOS 设备上安装程序
  14. com.google.common.collect.Lists#transform使用注意
  15. 深度学习实践系列(1)- 从零搭建notMNIST逻辑回归模型
  16. 【Redis篇】初始Redis与Redis安装
  17. MS SQL批量生成作业脚本方法介绍总结
  18. Python之字符串操作
  19. bzoj 4326: NOIP2015 运输计划(二分+树链剖分)
  20. 操作系统の实验四 windows中线程的创建和同步控制

热门文章

  1. Noip2016滚粗记QAQ
  2. bcc
  3. Codeforces Round #506 (Div. 3) 题解
  4. 用JSR的@Inject代替@Autowired完成自动装配
  5. C# new override
  6. 数据结构之(HDU2051 Bitset)
  7. MyBatis的SQL语句映射文件详解(三)----多参数传递的几种方式
  8. [POJ1286&amp;POJ2154&amp;POJ2409]Polya定理
  9. 让VC6.0编译出来的程序支持XP样式或XP风格
  10. 转:SWT中的Display 对象和 Shell对象