hdu2460 和 poj3694

poj3694:先预处理出询问边(u,v)的最小公共祖先lca{u,v}(用tarjan的lca离线算法)和桥的总数scc,最后每次从u到lca{u,v},v到lca{u,v},找出其中桥的数量,用scc减去,就是答案了。因为每次形成了圈,所以用并查集缩点,不然会TLE;写了一天就T在这儿了。

hdu2460:尼玛啊?hdu太坑爹了,个种深搜都不行啊? 连并查集路径压缩 的深搜都不行 害我改了一晚上…各种RE啊?其它和poj3694一样。

//poj3694 代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 100005
#define maxc 400005
using namespace std;
struct node
{
     int e,next;
}edge[maxc],Tedge[2005];
struct node1
{
     int a,b;
}qurey[1005],fa[INF];
int num,top,scc,bleg[INF],st[INF],first1[INF],first[INF],dfn[INF],low[INF],blegs[INF];
int used[INF],edges[maxc],ancestor[INF],lca[2005],ids[maxc],fids[maxc],ids1[maxc],fids1[maxc];
int Find( int x)
{
     return bleg[x]==x?x:bleg[x]=Find(bleg[x]);
}
void Union( int a, int b)
{
     a=Find(a),b=Find(b);
     bleg[b]=a;
}
int Finds( int x)
{
     return blegs[x]==x?x:blegs[x]=Finds(blegs[x]);
}
void Unions( int a, int b)
{
     a=Finds(a),b=Finds(b);
     blegs[a]=b;
}
void tarjan( int v)
{
     dfn[v]=low[v]=++num;
     st[++top]=v;
     ancestor[Find(v)]=v;
     for ( int i=first[v];i!=-1;i=edge[i].next)
     {
         int u=edge[i].e;
         if (fids[ids[i]])
         continue ;
         fids[ids[i]]=1;
         if (!dfn[u])
         {
             fa[u].a=v,fa[u].b=i;
             tarjan(u);
             Union(v,u);
             ancestor[Find(v)]=v;
             low[v]=min(low[v],low[u]);
             if (low[u]>dfn[v])
             {
                 scc++;
                 edges[ids[i]]=1;
                 while ( true )
                 {
                     int x=st[top--];
                     if (x==u)
                     break ;
                 }
             }
         }
         else
         low[v]=min(low[v],dfn[u]);
     }
     used[v]=1;
     for ( int i=first1[v];i!=-1;i=Tedge[i].next)
     if (used[Tedge[i].e] && !fids1[ids1[i]])
     {
         lca[ids1[i]]=ancestor[Find(Tedge[i].e)];
         fids1[ids1[i]]=1;
     }
}
int main()
{
     int n,m,q,cas=0;
     while ( scanf ( "%d%d" ,&n,&m),m+n)
     {
         cas++;
         memset (first,-1, sizeof (first));
         memset (first1,-1, sizeof (first1));
         memset (dfn,0, sizeof (dfn));
         memset (edges,0, sizeof (edges));
         memset (fids,0, sizeof (fids));
         memset (fids1,0, sizeof (fids1));
         memset (used,0, sizeof (used));
         int a,b,nume,number;
         number=nume=top=scc=num=0;
         for ( int i=1;i<=n;i++)
         blegs[i]=fa[i].a=bleg[i]=i;
         while (m--)
         {
             scanf ( "%d%d" ,&a,&b);
             ids[nume]=number;
             edge[nume].e=b,edge[nume].next=first[a],first[a]=nume++;
             ids[nume]=number++;
             edge[nume].e=a,edge[nume].next=first[b],first[b]=nume++;
         }
         number=nume=0;
         scanf ( "%d" ,&q);
         for ( int i=0;i<q;i++)
         {
             scanf ( "%d%d" ,&a,&b);
             qurey[i].a=a,qurey[i].b=b;
             ids1[nume]=number;
             Tedge[nume].e=b,Tedge[nume].next=first1[a],first1[a]=nume++;
             ids1[nume]=number++;
             Tedge[nume].e=a,Tedge[nume].next=first1[b],first1[b]=nume++;
         }
         tarjan(1);
         printf ( "Case %d:n" ,cas);
         for ( int i=0;i<q;i++)
         {
             if (scc!=0)
             {
                 for ( int k=qurey[i].a,j=Finds(fa[k].a);j!=Finds(qurey[i].a);k=j,j=Finds(fa[j].a))
                 {
                     Unions(qurey[i].a,j);
                     if (edges[ids[fa[k].b]])
                     {
                         scc--;
                         edges[ids[fa[k].b]]=0;
                     }
                     if (j==Find(lca[i]))
                     break ;
                 }
                 for ( int k=qurey[i].b,j=Finds(fa[k].a);j!=Finds(qurey[i].b);k=j,j=Finds(fa[j].a))
                 {
                     Unions(qurey[i].b,j);
                     if (edges[ids[fa[k].b]])
                     {
                         scc--;
                         edges[ids[fa[k].b]]=0;
                     }
                     if (j==Finds(lca[i]))
                     break ;
                 }
                 Union(qurey[i].a,qurey[i].b);
             }
             printf ( "%dn" ,scc);
         }
         printf ( "n" );
     }
     return 0;
}
 

//hdu2460  代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 100005
#define maxc 400005
using namespace std;
struct node
{
     int e,next;
}edge[maxc],Tedge[2005];
struct node1
{
     int a,b;
}qurey[1005],fa[INF];
int num,top,scc,bleg[INF],st[INF],first1[INF],first[INF],dfn[INF],low[INF],blegs[INF],vis[INF];
int used[INF],edges[maxc],ancestor[INF],lca[2005],ids[maxc],fids[maxc],ids1[maxc],fids1[maxc];
int Find( int x)
{
     int y=x;
     while (y!=bleg[y])
     y=bleg[y];
     while (x!=bleg[x])
     {
         int px=bleg[x];
         bleg[x]=y;
         x=px;
     }
     return y;
}
void Union( int a, int b)
{
     a=Find(a),b=Find(b);
     bleg[b]=a;
}
int Finds( int x)
{
     int y=x;
     while (y!=blegs[y])
     y=blegs[y];
     while (x!=blegs[x])
     {
         int px=blegs[x];
         blegs[x]=y;
         x=px;
     }
     return y;
}
void Unions( int a, int b)
{
     a=Finds(a),b=Finds(b);
     blegs[a]=b;
}
void tarjan( int v)
{
     st[++top]=v;
     while (top)
     {
         v=st[top];
         if (!vis[v])
         dfn[v]=low[v]=++num,vis[v]=1;
         ancestor[Find(v)]=v;
         int i;
         for (i=first[v];i!=-1;i=edge[i].next)
         {
             int u=edge[i].e;
             if (fids[ids[i]])
             continue ;
             fids[ids[i]]=1;
             if (!vis[u])
             {
                 fa[u].a=v,fa[u].b=i;
                 break ;
             }
             else if (vis[u]==1)
             low[v]=min(low[v],dfn[u]);
         }
         if (i==-1 && top>1)
         {
             Union(st[top-1],v);
             low[st[top-1]]=min(low[st[top-1]],low[v]);
             if (low[v]>dfn[st[top-1]])
             {
                 scc++;
                 edges[ids[fa[v].b]]=1;
             }
         }
         if (i==-1)
         {
             vis[v]=2;
             top--;
             used[v]=1;
             for (i=first1[v];i!=-1;i=Tedge[i].next)
             if (used[Tedge[i].e] && !fids1[ids1[i]])
             {
                 lca[ids1[i]]=ancestor[Find(Tedge[i].e)];
                 fids1[ids1[i]]=1;
             }
         }
         else
         st[++top]=edge[i].e;
     }
}
int main()
{
     int n,m,q,cas=0;
     while ( scanf ( "%d%d" ,&n,&m),m+n)
     {
         cas++;
         memset (first,-1, sizeof (first));
         memset (first1,-1, sizeof (first1));
         memset (dfn,0, sizeof (dfn));
         memset (edges,0, sizeof (edges));
         memset (fids,0, sizeof (fids));
         memset (fids1,0, sizeof (fids1));
         memset (used,0, sizeof (used));
         memset (vis,0, sizeof (vis));
         int a,b,nume,number;
         number=nume=top=scc=num=0;
         for ( int i=1;i<=n;i++)
         blegs[i]=fa[i].a=bleg[i]=i;
         while (m--)
         {
             scanf ( "%d%d" ,&a,&b);
             ids[nume]=number;
             edge[nume].e=b,edge[nume].next=first[a],first[a]=nume++;
             ids[nume]=number++;
             edge[nume].e=a,edge[nume].next=first[b],first[b]=nume++;
         }
         number=nume=0;
         scanf ( "%d" ,&q);
         for ( int i=0;i<q;i++)
         {
             scanf ( "%d%d" ,&a,&b);
             qurey[i].a=a,qurey[i].b=b;
             ids1[nume]=number;
             Tedge[nume].e=b,Tedge[nume].next=first1[a],first1[a]=nume++;
             ids1[nume]=number++;
             Tedge[nume].e=a,Tedge[nume].next=first1[b],first1[b]=nume++;
         }
         tarjan(1);
         printf ( "Case %d:n" ,cas);
         for ( int i=0;i<q;i++)
         {
             if (scc!=0)
             {
                 for ( int k=qurey[i].a,j=Finds(fa[k].a);j!=Finds(qurey[i].a);k=j,j=Finds(fa[j].a))
                 {
                     Unions(qurey[i].a,j);
                     if (edges[ids[fa[k].b]])
                     {
                         scc--;
                         edges[ids[fa[k].b]]=0;
                     }
                     if (j==Find(lca[i]))
                     break ;
                 }
                 for ( int k=qurey[i].b,j=Finds(fa[k].a);j!=Finds(qurey[i].b);k=j,j=Finds(fa[j].a))
                 {
                     Unions(qurey[i].b,j);
                     if (edges[ids[fa[k].b]])
                     {
                         scc--;
                         edges[ids[fa[k].b]]=0;
                     }
                     if (j==Finds(lca[i]))
                     break ;
                 }
                 Union(qurey[i].a,qurey[i].b);
             }
             printf ( "%dn" ,scc);
         }
         printf ( "n" );
     }
     return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值