XJOI 38 感想
来源:互联网 发布:mac 拍照照片在哪里 编辑:程序博客网 时间:2024/05/30 12:30
第二题:对于一个元素集合最大值减最小值小于等于某个值可以用单调队列来维护
第三题:
给你一张图,500000组询问询问x到y之间是否存在一条经过奇数个点的路径
这道题利用了点双连通分量的性质: 一个点双连通分量如果有一个奇环,那么你如果经过其中两个不同点就一定可以改变路径的奇偶性,这个证明比较玄学,我也不确定,我是利用一个存在奇环的点双连通分量中的一个点一定在一个奇环上来证的.(雾);奇环用二分图染色来求
然后zrf给出了一种比较好的方法来建树,对于每一个点双新建一个节点与点双中的所有点连边,这样就可以方便的判断点的出入情况了.
然而我利用dfs树也给出了一种做法,我们说其具备改变奇偶的能力,当且仅当其和其父亲均在一个有奇环的点双中,这样做能够保证不是只仅仅经过一个点.(一定有一个进点一个出点).做法比较容易.
这类构造体往往与联通分量有关,下次看到改变奇偶性要想到奇环,还有zrf做法适应普遍题目,我的算法只是一个trick.
%:pragma GCC optimize(4)#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<stack>#include<vector>using namespace std;const int N = 1000005;const int M = N * 2;int fir[N] , ne[M] , to[M] , cnt = 1 , scc_no[N] , stk[N] , tot , depth[N] , vis[N] , dfs_clock , dfn[N] , low[N] , cut[N] , scc_cnt , col[N];int n , m ,q , x , y , is_two[N] , can[N] , valid[N][26] , fa[N] , st[N][26];void add(int x , int y) { ne[++ cnt] = fir[x]; fir[x] = cnt; to[cnt] = y;}void link(int x, int y) { add(x , y); add(y , x);}#define Foreachson(i , x) for(int i = fir[x];i;i = ne[i])#define Pair pair<int,int>void DFS(int x, int f) { depth[x] = depth[f] + 1; vis[x] = 1; fa[x] = f; Foreachson(i , x) { int V = to[i]; if(vis[V]) continue; DFS(V , x); }}vector<int>scc_col[N];vector<Pair>scc_edge[N];vector<int>G[N];stack<Pair>S;void dfs(int x , int f) { low[x] = dfn[x] = ++ dfs_clock; int py= 0; Foreachson(i , x) { int V = to[i]; py ++; if(!dfn[V]) { S.push(make_pair(x , V)); dfs(V , x); if(dfn[x] <= low[V]) { cut[x] = 1; ++ scc_cnt; scc_col[scc_cnt].clear(); for(;;) { Pair ind = S.top(); S.pop(); scc_edge[scc_cnt].push_back(ind); int u = ind.first , v = ind.second; if(scc_no[u] != scc_cnt) { scc_no[u] = scc_cnt; scc_col[scc_cnt].push_back(u); } if(scc_no[v] != scc_cnt) { scc_no[v] = scc_cnt; scc_col[scc_cnt].push_back(v); } if(ind == (make_pair(x , V))) break; } } low[x] = min(low[x] , low[V]); } else if(dfn[V] < dfn[x] && V != f) { low[x] = min(low[x] , low[V]); S.push(make_pair(V , x)); } }// if(py == 1 && x== 1) cut[x] = 0;}int getans(int x , int Col) { col[x] = Col; for(int i = 0;i <(int)G[x].size();i ++) { int V = G[x][i]; if(col[V] == Col) return 0; if(col[V] == (Col ^ 1)) continue; if(!getans(V , Col ^ 1)) return 0; } return 1;}void calc(int x) { for(int i = 0;i <(int) scc_col[x].size();i ++) { int it = scc_col[x][i]; col[it] = x * 2 - 1; G[it].clear(); } for(int i = 0;i <(int) scc_edge[x].size();i ++) { Pair now = scc_edge[x][i]; G[now.first].push_back(now.second); G[now.second].push_back(now.first); } for(int i = 0;i <(int) scc_col[x].size();i ++) { int it = scc_col[x][i]; if(col[it] != x * 2 && col[it] != x * 2 + 1) { int xxx = getans(it , x * 2); if(!xxx) { is_two[x] = 0; return; } } } is_two[x] = 1;}void getit(void) { for(int i = 1;i <= scc_cnt;i ++) { calc(i); if(!is_two[i]) { for(int j = 0;j <(int) scc_col[i].size();j ++) { can[scc_col[i][j]] = 1; } } }}void dfs2(int x , int f) { valid[x][0] = can[x] & can[f]; st[x][0] = f; for(int i = 1;i <= 25;i ++) { st[x][i] = st[st[x][i - 1]][i - 1]; valid[x][i] = valid[x][i - 1] | valid[st[x][i - 1]][i - 1]; } Foreachson(i , x) { int V = to[i]; if(fa[V] == x) { dfs2(V , x); } }}bool get(int x , int y) { if(depth[x] > depth[y]) swap(x , y); int ans = 0; for(int i = 25;i >= 0;i --) { if(depth[st[y][i]] >= depth[x]) { ans |= valid[y][i]; y = st[y][i]; } } if(x == y) return ans; for(int i = 25;i >= 0;i --) if(st[x][i] != st[y][i]) { ans |= valid[x][i]; ans |= valid[y][i]; x = st[x][i]; y = st[y][i]; } ans |= valid[y][0]; ans |= valid[x][0]; return ans;}int main(void) { scanf("%d%d%d",&n,&m,&q); for(int i = 1;i <= m;i ++) { scanf("%d%d",&x,&y); link(x , y); } DFS(1 , 0); dfs(1 , 0); getit(); dfs2(1 , 0); for(int i = 1;i <= q;i ++) { scanf("%d%d",&x,&y); if((depth[x] - depth[y]) % 2 == 0 && !get(x , y)) puts("NIE"); else puts("TAK"); }}
阅读全文
1 0
- XJOI 38 感想
- XJOI 公交线路
- [XJOI]栈
- XJOI泡泡糖
- XJOI 迷你火车头
- XJOI 1003 质因数分解
- [XJOI]黑白树
- 【XJOI】path 题解
- [XJOI]排序列表
- xjoi奋斗群群赛2
- xjoi奋斗群群赛3
- xjoi奋斗群群赛4
- xjoi奋斗群群赛5
- XJOI划水总结
- xjoi奋斗群群赛6
- xjoi奋斗群群赛7
- XJOI Week1 奋斗总结
- xjoi奋斗群群赛8
- 点击li,输出对应li的下标
- MT 102+ Multiple Customer Credit Transfer多客户信用转账
- Linux学习总结
- TCP 和Http 和 Scoket 的区别
- Apache Spark 2.2.0 中文文档
- XJOI 38 感想
- 记录一下Material Dialogs的使用
- Django Temples中的注意点
- 最大流之Dinic算法
- SSM项目整合笔记-原项目重构
- hdu 6047
- 51nod 1350 斐波那契表示【斐波那契数列】
- Leetcode-4-Median of Two Sorted Arrays
- python 一键升级所有安装包