poj 3694 Network
2013-11-01 20:24
330 查看
分析:先缩点成树,然后模拟LCA过程。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn = 200500; //const int maxm = 405000; struct Node{ int v,next; }e[maxn*4],tree[maxn*4]; int bridge,vis[maxn],pre[maxn],head[maxn]; int dfn[maxn],low[maxn],head1[maxn],id[maxn],index,top,num,scc,sta[maxn]; void add(int a,int b){ e[num].v=b; e[num].next=head[a]; head[a]=num++; } void add_tree(int a,int b){ tree[num].v=b; tree[num].next=head1[a]; head1[a]=num++; } void init(){ top=0; scc=num=index=0; memset(dfn,0,sizeof(dfn)); } void tarjan(int u,int fa){ dfn[u]=low[u]=++index; sta[++top]=u; int cnt=0; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); } else if(fa==v){ if(cnt) low[u]=min(low[u],dfn[v]); cnt++; } else{ low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ int x; scc++; do{ x=sta[top--]; id[x]=scc; // printf("%d ",x); }while(x!=u); // printf("\n"); } } int ran[maxn]; void lca_dfs(int u,int dept,int fa){ ran[u]=dept; for(int i=head1[u];i!=-1;i=tree[i].next){ int v=tree[i].v; if(v==fa) continue; low[v]=1; lca_dfs(v,dept+1,u); pre[v]=u; } } void lca(int u,int v){ while(ran[u]>ran[v]){ if(low[u]){ low[u]=0; bridge--; } u=pre[u]; } while(ran[u]<ran[v]){ if(low[v]){ low[v]=0; bridge--; } v=pre[v]; } while(u!=v){ if(low[u]){ bridge--; low[u]=0; } if(low[v]){ bridge--; low[v]=0; } u=pre[u]; v=pre[v]; } } int main(){ int n,m,con=1; while(~scanf("%d %d",&n,&m) && (n+m)){ init(); for(int i=0;i<=n;i++){ head[i]=-1; vis[i]=0; } for(int i=0;i<m;i++){ int a,b; scanf("%d %d",&a,&b); add(a,b); add(b,a); } for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjan(i,-1); } } num=0; for(int i=0;i<=n;i++){ head1[i]=-1; low[i]=0; } for(int u=1;u<=n;u++){ // vis[u]=1; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; // if(vis[v]) continue; if(id[u]!=id[v]){ add_tree(id[u],id[v]); // printf("link----%d %d\n",id[u],id[v]); } } } lca_dfs(1,1,-1); bridge=scc-1; // for(int i=1;i<=scc;i++){ // printf("%d---%d\n",i,ran[i]); // } int q; scanf("%d",&q); printf("Case %d:\n",con++); while(q--){ int a,b; scanf("%d %d",&a,&b); if(id[a]!=id[b]){ lca(id[a],id[b]); } // else{ printf("%d\n",bridge); // } } // printf("%d\n",bridge); // for(int i=1;i<=n;i++){ // printf("%d---%d\n",i,id[i]); // } } }
相关文章推荐
- iwebshop二次开发(2)
- (原)Win8 关机批处理脚本
- 用OpenGL实现 中点画圆法
- Ruby开发入门
- Ubuntu下SVN的安装和配置
- Ruby开发入门
- unorder_set<typename T> 学习
- CVPR2013-reading list
- Qt模块化笔记之sql——执行sql语句
- 编程序,输出一个乘法口诀表
- 用OPenGL实现 Bresenham画线算法
- 黑马程序员_网络编程
- oracle学习第一天
- 如何判断一个app是system/app还是data/app下面的?
- sockaddr和sockaddr_in的区别
- 国产手机再次发力,是否可以阻击三星苹果
- 设置 gridview 数据 居中 显示
- C++ char*,const char*,string的相互转换
- KGTP, Linux内核中的GDB快刀
- 如何做合格黑客并从事网络安全