codeforces 652E . Pursuit For Artifacts 强连通分量
2016-03-28 10:47
531 查看
题目链接
题目大意: 给一个图, n个点m条边, 某些边上面有权值。一条边只能走一次, 给两个点s, t。 问你, 从s到t能否经过有权值的边。
首先肯定要缩点, 然后看同一个连通分量里面的边, 是否有有权值的边, 如果有, 那么这个联通块赋值为1。
看两个点s, t。 如果两个点在同一个联通分量里面, 看这个连通分量的值是否为1。
否则的话, 看从s到t路径上的边有没有边的权值为1, 或者是经过的连通分量有没有值为1的。 如果有就yes, 否则no。
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <complex> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef complex <double> cmx; typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; const int maxn = 3e5+5; int head[maxn], num, s[maxn], dfn[maxn], low[maxn]; int vis[maxn], instack[maxn], st[maxn], ok[maxn], top, cnt, deep; pair <int, pll> ed[300005]; struct val { int u, ok; }; struct node { int to, nextt, w; }e[maxn*2]; void add(int u, int v) { e[num].to = v, e[num].nextt = head[u], head[u] = num++; } void add(int u, int v, int w) { e[num].to = v, e[num].nextt = head[u], e[num].w = w, head[u] = num++; } void tarjan(int u, int fa) { st[++top] = u; instack[u] = 1; low[u] = dfn[u] = ++deep; for(int i = head[u]; ~i; i = e[i].nextt) { int v = e[i].to; if(v == fa) continue; if(!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); } else if(instack[v]) { low[u] = min(low[u], dfn[v]); } } if(dfn[u] == low[u]) { ++cnt; int v; do { v = st[top--]; instack[v] = 0; s[v] = cnt; } while(u != v); } } int bfs(int u, int v) { queue <val> q; q.push(val{u, ok[u]}); vis[u] = 1; while(!q.empty()) { val tmp = q.front(); q.pop(); if(tmp.u == v&&tmp.ok) return 1; for(int i = head[tmp.u]; ~i; i = e[i].nextt) { int ve = e[i].to; if(vis[ve]) continue; vis[ve] = 1; val temp = tmp; if(ok[ve] || e[i].w) { temp.ok = 1; } temp.u = ve; q.push(temp); } } return 0; } int main() { int n, m, a, b; cin>>n>>m; mem1(head); for(int i = 0; i < m; i++) { scanf("%d%d%d", &ed[i].fi, &ed[i].se.fi, &ed[i].se.se); add(ed[i].fi, ed[i].se.fi); add(ed[i].se.fi, ed[i].fi); } tarjan(1, 0); mem1(head); num = 0; for(int i = 0; i < m; i++) { int u = ed[i].fi, v = ed[i].se.fi; if(s[u] == s[v]) { if(ed[i].se.se) { ok[s[u]] = 1; } continue; } add(s[u], s[v], ed[i].se.se); add(s[v], s[u], ed[i].se.se); } cin>>a>>b; if(s[a] == s[b]) { if(ok[s[a]]) { puts("YES"); } else { puts("NO"); } } else { if(bfs(s[a], s[b])) { puts("YES"); } else { puts("NO"); } } return 0; }
相关文章推荐
- hdu 5493 Queue 树状数组第K大或者二分
- 让UITableview里自定义分区头部随着滑动而滑动
- requireJs模块化实现返回顶部的功能
- BlockingQueue
- c# Dictionary的TryGetValue的用法
- iOS 动画讲解(一)之UIView动画
- OpenCV学习笔记---HighGUI的初步
- UML时序图画法简介-sequenceDiagram
- queue
- Xcode 插件因为UUID原因不能使用解决办法
- android 漂亮的开源ui框架
- 《iOS Human Interface Guidelines》——Progress View
- 背水一战 Windows 10 (5) - UI: 标题栏
- LeetCode Verify Preorder Sequence in Binary Search Tree
- [LeetCode] Verify Preorder Sequence in Binary Search Tree 验证二叉搜索树的先序序列
- 60. Permutation Sequence
- andorid UI事件 监听器
- andorid UI事件
- UITabBarController简单介绍
- UITableviewcell的性能问题