tarjan -LCA POJ-3417-Network
来源:互联网 发布:ps4全境封锁网络卡 编辑:程序博客网 时间:2024/04/26 06:16
先放一下tarjan离线求LCA的模板
就是先dfs 然后访问新边的时候,如果碰到标记过的点,那么就说明被dfs过了
两个点找lca
void addedge2(int x,int y){ pra[e].to = y; pra[e].next = head2[x]; head2[x] = e++;}int f[SIZE_D];int findc(int x){ if (f[x] == x) return x; return f[x] = findc(f[x]);}int flag[SIZE_D],dp[SIZE_D];void tarjan(int ver,int fa){ f[ver] = ver; for (int i = head[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (u != fa){ tarjan(u,ver); f[u] = ver; } } flag[ver] = 1; ///标记flag为何要放在两个图遍历的中间呢?能不能放后面?能不能放前面? for (int i = head2[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (flag[u] != 0){ int t = findc(u); dp[u]++;dp[ver]++;dp[t]-= 2; } }}
啊呀呀……说一下这道题题意
题意:有一棵树,有n个点,现在再增加m条新边,问你去掉原来老边,去掉一条新边,使得图不连通,有几种方案数?
做法:一条边,假如存在在一个环中,那就去掉它,再去掉环中的另一条边就可以了。假如不存在在一个环中,那它就是一个桥(去掉这条边图不连通)。假如存在两个或者两个以上的环中,那么去掉这条边,无论再去掉哪条边,都不会使图不连通。
用点覆盖度表示当前点的上一条边在几个环中。
做法就是每次加进来一条新的边,那就找这两个节点的LCA ,d【v】++;d【u】++;d【lca】-=2;
然后dfs 每个点的dp值就是孩子节点(不包括孙子)的dp值之和
poj交题碰到的奇葩事:
1.老是502,504 我已经不爱poj了TAT
2.数组开小了居然返回的是TLE
3.没有把数组全部初始化只把数组部分初始化 居然返回的是RE
放代码
/*给出原有边之后就先预处理所有边的父亲每加一条边,加到u和v上就把u和v直到LCA的祖先节点都加1.然后祖先节点先加2再减2从第一个到最后一个算每个节点的覆盖度若覆盖度是0 那么就ans+= 新加的边若覆盖度是1 那么就是删去这条边 ans+= 1关于新加边存在x=y的情况,没判掉wa图论三大坑自环重边点序号*/#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define SIZE_D 200005#define SIZE_B 400005using namespace std;int N,M;struct pp{ int to,next;}pra[SIZE_B];int e,head[SIZE_D];int head2[SIZE_D];void init(){ e = 0; memset(head, -1, sizeof(head)); memset(head2, -1, sizeof(head2));}void addedge(int x,int y){ pra[e].to = y; pra[e].next = head[x]; head[x] = e++;}void addedge2(int x,int y){ pra[e].to = y; pra[e].next = head2[x]; head2[x] = e++;}int f[SIZE_D];int findc(int x){ if (f[x] == x) return x; return f[x] = findc(f[x]);}int flag[SIZE_D],dp[SIZE_D];void tarjan(int ver,int fa){ f[ver] = ver; for (int i = head[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (u != fa){ tarjan(u,ver); f[u] = ver; } } flag[ver] = 1; ///标记flag为何要放在两个图遍历的中间呢?能不能放后面?能不能放前面? for (int i = head2[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (flag[u] != 0){ int t = findc(u); dp[u]++;dp[ver]++;dp[t]-= 2; } }}void getdp(int ver,int fa){ for (int i = head[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (u != fa){ getdp(u,ver); dp[ver]+=dp[u]; } }}bool kn[SIZE_D];int main(){ //freopen("input.txt","r",stdin); while (~scanf("%d %d",&N,&M)){ init(); memset(kn,0,sizeof (kn));//增加了kn数组看看是从哪个下标开始的 for (int i = 1; i < N; i++){ int tempx,tempy; scanf("%d %d",&tempx,&tempy); kn[tempx] = kn[tempy] = 1; addedge(tempx,tempy); addedge(tempy,tempx); } for (int i = 0; i < M; i++){ int tempx,tempy; scanf("%d %d",&tempx,&tempy); kn[tempx] = kn[tempy] = 1; addedge2(tempx,tempy); addedge2(tempy,tempx); } int ispran = 0; memset(flag,0,sizeof(flag)); memset(dp,0,sizeof(dp)); int root; for (int i = 0; i < SIZE_D-5; i++){ if (kn[i] == 1){ tarjan(i,-1); getdp(i,-1); root = i; break; } } int sum = 0; int res = 0; for (int i = 0; i < SIZE_D-5; i++){ if (kn[i] == 1 && i != root){ if (dp[i] == 1)res++; if (dp[i] == 0) res +=M; sum++; if (sum == N) break; } } printf("%d\n",res); } return 0;}
0 0
- tarjan -LCA POJ-3417-Network
- Tarjan+LCA POJ 3694 Network
- POJ 3694 Network tarjan+LCA
- POJ 3694 Network(tarjan+lca)
- poj 3694 Network(tarjan + LCA)
- poj 3694 Network(tarjan+LCA求割边)
- poj 3694 Network(Tarjan+LCA)
- POJ 3694Network (tarjan bcc + LCA)
- POJ 3694 Network(Tarjan求割边+LCA)
- POJ 3417 Network LCA
- POJ 题目3694 Network(tarjan,LCA,求桥)
- Network poj 3694(tarjan 求割边 + lca(朴素的))
- POJ-3694-Network(Tarjan+LCA+并查集)
- 【LCA】 POJ 3417 Network 记数
- POJ 3417 Network (LCA + DP)
- poj3694 Network 【图论-Tarjan-Lca】
- poj 1470--tarjan--LCA
- POJ 3694 Tarjan+LCA
- OC多线程
- java多进程 -CD7-孙鑫-(1)-程序/进程/线程/设置后台线程/将当前线程暂停
- Java中的垃圾回收器
- Grunt 从零开始
- 对C++中类的继承方式的认识
- tarjan -LCA POJ-3417-Network
- 2015年读书
- 提示框与动画的结合使用
- 1.4_Session and Flash scopes
- 企业级开发的思考
- HTML5 的诞生及一些优势
- Hdu 10000的阶乘
- XF&X
- 2015.3.31大盘走势分析,及次日行情预测。