poj3694 Network 边双联通缩点+离线LCA
来源:互联网 发布:linux中tar命令 编辑:程序博客网 时间:2024/04/26 06:16
给一个联通的图,然后依次添加Q条边,每次添加边之后,图中还剩多少条桥?先求一下边双联通重构成一棵树,然后就是求LCA了,查询的时候从两个点开始往祖先一边爬一边标记掉沿途的边,根据每次标记掉的点以及上一次的答案就可以递推出当前的答案...切记一点这题有重边...所以求ebc的时候记得用边判父节点...思路不是很难,但代码写起来太坑爹了......
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <vector>#include <stack>using namespace std;typedef long long ll;const int maxn=155000;struct EDGE{ int v,w,next;}ed1[maxn<<2],ed2[maxn<<2],ed3[4040];int g[maxn];int gg[maxn];int qe[maxn];int p1,p2,p3;stack<int> s;int pre[maxn];int id[maxn],dfs_clock,ebc_cnt;int deg[maxn];bool ok[maxn];int n,m,k,p,q;int dfs(int u,int frm){ int lowu=pre[u]=++dfs_clock; s.push(u); for (int j=g[u];j!=-1; j=ed1[j].next) { int v=ed1[j].v; if (j==(frm^1)) continue; if (!pre[v]) { int lowv=dfs(v,j); lowu=min(lowu,lowv); } else if (pre[v]<pre[u]) { lowu=min(lowu,pre[v]); } } if (lowu==pre[u]) { ebc_cnt++; while (true) { int x=s.top(); s.pop(); id[x]=ebc_cnt; if (x==u) break; } } return lowu;}void findebc(int n){ memset(pre,0,sizeof pre); memset(id,0,sizeof id); while(!s.empty()) s.pop(); for (int i=1; i<=n; i++) { if (!pre[i]) dfs(i,-1); }}int dis[maxn];bool vis[maxn];int fa[maxn];int res[maxn][3];int fr[maxn];int find(int x){ if (x==fa[x]) return fa[x]; return fa[x]=find(fa[x]);}void lca(int u){ vis[u]=true; fa[u]=u; int v; for (int j=qe[u]; j!=-1; j=ed3[j].next) { v=ed3[j].v; if (vis[v]) { res[ed3[j].w][2]=find(v); } } for (int j=gg[u]; j!=-1; j=ed2[j].next) { v=ed2[j].v; if (!vis[v]) { fr[v]=u; dis[v]=dis[u]+1; lca(v); fa[v]=u; } }}int ans[maxn];int main(){// freopen("in.txt","r",stdin); int x,y; int cp=0; while(~scanf("%d%d",&n,&m)) { if (n==0 && m==0) break; cp++; printf("Case %d:\n",cp); memset(g,-1,sizeof g); memset(gg,-1,sizeof gg); memset(qe,-1,sizeof qe); p1=p2=p3=0; for (int i=1; i<=m; i++) { scanf("%d%d",&x,&y); ed1[p1].v=y; ed1[p1].w=1; ed1[p1].next=g[x]; g[x]=p1; p1++; ed1[p1].v=x; ed1[p1].w=1; ed1[p1].next=g[y]; g[y]=p1; p1++; } ebc_cnt=0; findebc(n); for (int i=1; i<=n; i++) for (int j=g[i]; j!=-1; j=ed1[j].next) { x=id[i]; y=id[ed1[j].v]; if (x!=y) { ed2[p2].v=y; ed2[p2].w=1; ed2[p2].next=gg[x]; gg[x]=p2; p2++; ed2[p2].v=x; ed2[p2].w=1; ed2[p2].next=gg[y]; gg[y]=p2; p2++; } } int sum=ebc_cnt-1; memset(vis,false,sizeof vis); memset(res,0,sizeof res); scanf("%d",&q); for (int i=1; i<=q; i++) { scanf("%d%d",&x,&y); x=id[x]; y=id[y]; ed3[p3].v=y; ed3[p3].w=i; ed3[p3].next=qe[x]; qe[x]=p3; p3++; ed3[p3].v=x; ed3[p3].w=i; ed3[p3].next=qe[y]; qe[y]=p3; p3++; res[i][0]=x; res[i][1]=y; } dis[0]=0; lca(1); memset(ans,0,sizeof ans); memset(ok,false,sizeof ok); ans[0]=sum; for (int i=1; i<=q; i++) { x=res[i][0]; y=res[i][1]; int t=res[i][2]; ans[i]=ans[i-1]; while (x!=t) { if (!ok[x]) ans[i]--,ok[x]=true; x=fr[x]; } while (y!=t) { if (!ok[y]) ans[i]--,ok[y]=true; y=fr[y]; } } for (int i=1; i<=q; i++) printf("%d\n",ans[i]); printf("\n"); } return 0;}
0 0
- poj3694 Network 边双联通缩点+离线LCA
- POJ3694-Network(Tarjan缩点+LCA)
- POJ3694-Network(LCA+边联通分量+桥)
- POJ3694 Network 割边+LCA
- POJ3694 Network 割边 LCA
- poj3694--Network(双连通缩点+lca)
- POJ 3694 Network 边双联通+缩点+LCA+统计桥
- POJ3694 Network(边双连通+LCA)
- poj3694(边双联通分量)
- HDU 2460 Network 边双联通+LCA
- hdu2460&&poj3694 缩点+lca变形
- poj3694 Network 【图论-Tarjan-Lca】
- poj 3694双联通缩点+LCA
- poj3694+hdu2460 求桥+缩点+LCA/tarjan
- POJ3694(tarjan缩点+并查集+LCA)
- 点双联通+缩点+LCA(HDU3686)
- POJ 3694Network 双联通分量 + lca
- poj 3694Network 双联通分量+lca
- 2014之实习A计划
- 大乐透
- WCF(三)制作WCF安装包(Windows Services版)
- cocos2dx 2.0 和cocos2dx 2.2的区别
- position属性知一二
- poj3694 Network 边双联通缩点+离线LCA
- 我的vim配置和solardark主题
- VB6中双精度和单精度数据类型的比较
- Cocos2d-x-3c 设计之路 CocosBase CocosNet CocosWidget
- C# .NET4.0 混合模式程序集异常
- 你必须非常努力,才能看起来毫不费力
- 匈牙利命名法则
- 家庭局域网开启AP隔离利用无线路由器互连
- 【iOS7的一些总结】5、iOS中的内存管理