首页 > 代码库 > Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路
Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路
题目来源:Light OJ 1168 Wishing Snake
题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思
从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点
思路:首先缩点 每一个强连通分量里面的点都是可达的
缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达
所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1
特判只有一个强连通分量 和 开始第一个强连通分量是0所在的强连通分量
#include <cstdio> #include <cstring> #include <vector> #include <stack> #include <algorithm> using namespace std; const int maxn = 1010; vector <int> G[maxn]; int pre[maxn]; int low[maxn]; int sccno[maxn]; int dfs_clock; int scc_cnt; stack <int> S; int n, m; int in[maxn]; int out[maxn]; int cnt[maxn]; int id[maxn]; void dfs(int u) { pre[u] = low[u] = ++dfs_clock; S.push(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(!pre[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(!sccno[v]) low[u] = min(low[u], pre[v]); } if(pre[u] == low[u]) { scc_cnt++; while(1) { cnt[scc_cnt]++; int x = S.top(); S.pop(); sccno[x] = scc_cnt; if(x == u) break; } } } void find_scc() { dfs_clock = scc_cnt = 0; memset(sccno, 0, sizeof(sccno)); memset(pre, 0, sizeof(pre)); memset(cnt, 0, sizeof(cnt)); for(int i = 0; i <= n; i++) if(!pre[i]) dfs(i); } int main() { int cas = 1; int T; scanf("%d", &T); while(T--) { memset(id, -1, sizeof(id)); scanf("%d", &m); for(int i = 0; i <= 1000; i++) G[i].clear(); n = 0; id[0] = 0; while(m--) { int k; scanf("%d", &k); while(k--) { int u, v; scanf("%d %d", &u, &v); if(id[u] == -1) id[u] = ++n; if(id[v] == -1) id[v] = ++n; G[id[u]].push_back(id[v]); } } find_scc(); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); for(int i = 0; i <= n; i++) { for(int j = 0; j < G[i].size(); j++) { int v = G[i][j]; if(sccno[i] != sccno[v]) { in[sccno[v]]++; out[sccno[i]]++; } } } if(scc_cnt == 1) { printf("Case %d: YES\n", cas++); continue; } if(in[sccno[0]] != 0 || out[sccno[0]] == 0) { printf("Case %d: NO\n", cas++); continue; } int sum1 = 0, sum2 = 0, sum3 = 0; for(int i = 1; i <= scc_cnt; i++) { if(in[i] == 1 && out[i] == 1) sum1++; else if(in[i] == 1 && out[i] == 0) sum2++; else if(in[i] == 0 && out[i] == 1) sum3++; } if(sum2 != 1 || sum3 != 1 || sum1+sum2+sum3 != scc_cnt) printf("Case %d: NO\n", cas++); else printf("Case %d: YES\n", cas++); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。