poj 3694 Network
题意: 添加每条新连接后网络中桥的数目
// 超时 先放着了 ,下次改
//早上这代码超时了 下午改了,代码在下面
#include <iostream> #include <algorithm> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; #define MOD 1000000007 #define maxn 440000 #define maxm 100010 struct Edge{ int to; int num; int next; Edge(){}; Edge(int u,int v){to=u;next=v;} }E[maxn]; int V[maxm],num; bool tag[maxn]; int pre[maxm]; int dfst,bcc; int ans,eg; void init(int n){ eg=0; dfst=0; num=0; bcc=0; for(int i=1;i<=n;i++) V[i]=-1; } void add(int u,int v){ // 坑爹 原来原图没有重边的 郁闷 ,这里就耗了不少时间
int e; for(e=V[u];e!=-1;e=E[e].next) { if(v==E[e].to){ tag[E[e].num]=1;return; } } eg++; E[num].to=v; E[num].num=eg; E[num].next=V[u]; V[u]=num++; E[num].to=u; E[num].num=eg; E[num].next=V[v]; V[v]=num++; } int dfs(int u,int fa){ int lowu; lowu=pre[u]=++dfst; int v,e; for(e=V[u];e!=-1;e=E[e].next){ v=E[e].to; if(!pre[v]){ int lowv=dfs(v,u); lowu=min(lowu,lowv); if(lowv>pre[u]&&!tag[E[e].num]){ ans++; } } else if(v!=fa) lowu=min(lowu,pre[v]); } return lowu; } int main() { int n,m,Q; int u,v; int i,j=1; while(scanf("%d %d",&n,&m),n|m){ init(n); for(i=1;i<=m;i++){ scanf("%d %d",&u,&v); tag[i]=0; add(u,v); } printf("Case %d:\n",j++); scanf("%d",&Q); for(i=1;i<=Q;i++) tag[i+m]=0; while(Q--){ scanf("%d %d",&u,&v); add(u,v); for(i=1;i<=n;i++) pre[i]=0; ans=0; dfst=0; dfs(1,0); printf("%d\n",ans); } printf("\n"); } return 0; }
// 在原来的基础上 执行一次dfs 然就找两点的lca 我不愿去缩点 啥的, 网上看到一个不错的,就用了
// 就是先让 x,y达到同一深度 然后回走 直到碰面 边上遇到桥就标记删除
#include <iostream> #include <algorithm> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; #define MOD 1000000007 #define maxn 440000 #define maxm 100010 struct Edge{ int to; // int num; int next; Edge(){}; Edge(int u,int v){to=u;next=v;} }E[maxn]; int V[maxm],num; bool tag[maxm]; int fa[maxm]; int pre[maxm],low; int dfst; int ans; void init(int n){ dfst=0; num=0; ans=0; for(int i=1;i<=n;i++){ V[i]=-1; pre[i]=0; tag[i]=0; } } void add(int u,int v){ E[num].to=v; // E[num].num=m; E[num].next=V[u]; V[u]=num++; E[num].to=u; // E[num].num=m; E[num].next=V[v]; V[v]=num++; } int dfs(int u,int dp){ int lowu=pre[u]=dp; int v,e; for(e=V[u];e!=-1;e=E[e].next){ v=E[e].to; if(!pre[v]){ fa[v]=u; // printf("?%d %d %d\n",v,u,fa[v]); int lowv=dfs(v,dp+1); lowu=min(lowu,lowv); if(lowv>pre[u]){ ans++; tag[v]=true; //printf("%d",v); } } else if(v!=fa[u]) lowu=min(lowu,pre[v]); } // printf("%d %d ",u,fa[u]); return lowu; } void lca(int x,int y){ if(pre[x]>pre[y]) swap(x,y); while(pre[y]!=pre[x]){ if(tag[y]){ans--;tag[y]=false;} y=fa[y]; } while(x!=y){ if(tag[x]){ans--;tag[x]=false;} if(tag[y]){ans--;tag[y]=false;} x=fa[x];y=fa[y]; } } int main() { int n,m,Q; int u,v; int i,j=1; while(scanf("%d %d",&n,&m),n|m){ init(n); for(i=1;i<=m;i++){ scanf("%d %d",&u,&v); add(u,v); } fa[1]=1; dfs(1,1); printf("Case %d:\n",j++); scanf("%d",&Q);// for(i=1;i<=Q;i++) tag[i+m]=0; while(Q--){ scanf("%d %d",&u,&v); lca(u,v); printf("%d\n",ans); } printf("\n"); } return 0; }