Hdu 2874 Connections between cities

题意:

城市 道路  没有环 不一定连通的树 求两城市的最短距离 设想一下就是很多小树  那好办

思路:

lca离线算法 然后有个技巧就是 每次我们tarjan一棵树不是最后树的节点都访问过并且孩子全能找到老爸嘛 那么我们只要做做做做 做到全部的城市都访问过了  就行了 反正你做这颗小树的时候又不会影响到其他树的

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m;
const int N = 10005;
const int M = 1000005;
int f[N],Next[2*N],va[2*N],wi[2*N],Head[N];
int vis[N];
int nex[2*M],to[2*M],id[M],head[N],ans[M];
int find(int x)
{
    if(x!=f[x])f[x]=find(f[x]);
    return f[x];
}
int len,dis[N],l;
void add(int u,int v,int w)
{
    va[len]=v;
    wi[len]=w;
    Next[len]=Head[u];
    Head[u]=len++;
}
void add_x(int u,int v)
{
    to[l]=v;
    
    nex[l]=head[u];
    head[u]=l++;
}  

void lca(int u,int fa)
{
    f[u]=u;
    for(int i=Head[u];i!=-1;i=Next[i])
    {int v=va[i],w=wi[i];
    if(v!=fa){
        
        dis[v]=dis[u]+w;
        lca(v,u);
        f[v]=u;
        }
    }
    vis[u]=1;
    for(int i=head[u];i!=-1;i=nex[i])
    {
        int v=to[i];
        if(vis[v])
        {//puts("sadasd");
        ans[i/2]=find(v);
        }
    }
    
}

int main()
{
    int k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        len=l=0;
        memset(Head,-1,sizeof Head);
        memset(head,-1,sizeof head);
for(int i=0;i<m;i++)
    {
    
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }    
    dis[1]=0;
    for(int i=0;i<k;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        id[i]=u;
        add_x(u,v);
        add_x(v,u);
    }

memset(vis,0,sizeof vis);
    memset(f,0,sizeof f);
        memset(ans,-1,sizeof ans);
        for(int i=1;i<=n;i++)if(vis[i]==0)lca(i,0);
    for(int i=0;i<l;i+=2)
        {
            
            int a,b,c;
            a=to[i];
            b=id[i/2];    
    
        if(find(a)!=find(b))puts("Not connected");
          else  {c=ans[i/2];
          
         printf("%d\n",dis[a]+dis[b]-2*dis[c]);}
    }
    }
}

 

posted @ 2015-06-14 19:41  武略  阅读(208)  评论(0编辑  收藏  举报