HDU_2586 && HDU_2874 (LCA+tarjan)

How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8541    Accepted Submission(s): 2997



Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
 

Input
First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 

Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 

Sample Input
   
   
   
   
2 3 2 1 2 10 3 1 15 1 2 2 3 2 2 1 2 100 1 2 2 1
 

Sample Output
   
   
   
   
10 25 100 100
 

题意:在一棵树上,给出你每条边的权值,每次询问(u,v)之间距离多少。

分析:LCA+tarjan离线算法,模板题。用个数组depth[]来记录根节点走到每个点的路程,然后找出(u,v)的最近公共祖先LCA(u,v)。

那么,quary(u,v) = depth[u] + depth[v] - 2 * depth[LCA(u,v)]。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586

代码清单:

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<string>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxn = 1e5 + 5;
const int maxv = 1e5 + 5;

struct Edge{ int v,next,id; }edge[2*maxn];

struct Graph{ int v,next,dis; }graph[2*maxn];

int T;
int N,M;
int a,b,c;
int father[maxn];
int num,numq;
int head[maxn],headq[maxn];
pair<int,int>e[maxn];
int color[maxn],ans[maxn],depth[maxn];
bool vis[maxn];

int Find(int x){ return x!=father[x] ? father[x]=Find(father[x]) : father[x]; }


void tarjan_LCA(int u){
    vis[u]=true;color[u]=1;
    for(int i=headq[u];i!=-1;i=edge[i].next){
        int ID=edge[i].id;
        if(ans[ID]!=-1) continue;
        int v=edge[i].v;
        if(color[v]==0) continue;
        if(color[v]==1) ans[ID]=v;
        if(color[v]==2) ans[ID]=Find(v);
    }
    for(int i=head[u];i!=-1;i=graph[i].next){
        int vv=graph[i].v;
        int dis=graph[i].dis;
        if(!vis[vv]){
            depth[vv]=depth[u]+dis;
            tarjan_LCA(vv);
            color[vv]=2;
            father[vv]=u;
        }
    }
}

void add(int u,int v,int dis){
    graph[num].v=v;
    graph[num].dis=dis;
    graph[num].next=head[u];
    head[u]=num++;
}

void addq(int u,int v,int idx){
    edge[numq].v=v;
    edge[numq].id=idx;
    edge[numq].next=headq[u];
    headq[u]=numq++;
}

void init(){
    for(int i=1;i<=maxn;i++) father[i]=i;
    memset(edge,0,sizeof(edge));
    memset(graph,0,sizeof(graph));
    memset(head,-1,sizeof(head));
    memset(headq,-1,sizeof(headq));
    memset(color,0,sizeof(color));
    memset(ans,-1,sizeof(ans));
    memset(depth,0,sizeof(depth));
    memset(vis,false,sizeof(vis));
    num=numq=0;
}

void input(){
    scanf("%d%d",&N,&M);
    for(int i=1;i<N;i++){
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
        add(b,a,c);
    }
    for(int i=1;i<=M;i++){
        scanf("%d%d",&a,&b);
        e[i].first=a;e[i].second=b;
        addq(a,b,i);
        addq(b,a,i);
    }
}

void solve(){
    tarjan_LCA(1);
    for(int i=1;i<=M;i++){
        a=e[i].first;
        b=e[i].second;
        printf("%d\n",depth[a]+depth[b]-2*depth[ans[i]]);
    }
}

int main(){
    scanf("%d",&T);
    while(T--){
        init();
        input();
        solve();
    }return 0;
}

Connections between cities

                                                   Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                           Total Submission(s): 6400    Accepted Submission(s): 1679



Problem Description
After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city. For most of roads had been totally destroyed during the war, there might be no path between two cities, no circle exists as well.
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.
 

Input
Input consists of multiple problem instances.For each instance, first line contains three integers n, m and c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n represents the number of cities numbered from 1 to n. Following m lines, each line has three integers i, j and k, represent a road between city i and city j, with length k. Last c lines, two integers i, j each line, indicates a query of city i and city j.
 

Output
For each problem instance, one line for each query. If no path between two cities, output “Not connected”, otherwise output the length of the shortest path between them.
 

Sample Input
   
   
   
   
5 3 2 1 3 2 2 4 3 5 2 3 1 4 4 5
 

Sample Output
   
   
   
   
Not connected 6
Hint
Hint Huge input, scanf recommended.
 
题意:在一个森林中,给出边权值,然后每次询问(u,v)之间的距离,如果不存在则输出“Not connected”。

分析:LCA+tarjan离线算法,模板题。每次找个没有标记的点作为根节点跑一遍tarjan的时候记得把color数组初始化。因为之前染色的点属于前一棵树,跟当前的那棵树没有关系。

注意:此题用vector估计会MLE,所以用数组存。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874

代码清单:

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<string>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxn = 10000 + 5;
const int maxv = 10000 + 5;
const int maxq = 1000000 + 5;

struct MAX{
    int v,d;
    MAX(){}
    MAX(int v,int d){
        this -> v = v;
        this -> d = d;
    }
};

struct Q{ int v,id,next; }quary[2*maxq];
struct e{ int v,dis,next; }graph[2*maxn];
int n,m,q;
int a,b,c;
int father[maxn];
bool vis[maxn];
int ans[maxq];
int color[maxn];
int depth[maxn];
int nume,numq;
int heade[maxn];
int headq[maxn];

void init(){
    for(int i=1;i<=maxn;i++) father[i]=i;
    memset(ans,-1,sizeof(ans));
    memset(color,0,sizeof(color));
    memset(depth,0,sizeof(depth));
    memset(vis,false,sizeof(vis));
    memset(graph,0,sizeof(graph));
    memset(quary,0,sizeof(quary));
    memset(heade,-1,sizeof(heade));
    memset(headq,-1,sizeof(headq));
    nume=numq=0;
}

void add_E(int u,int v,int dis){
    graph[nume].v=v;
    graph[nume].dis=dis;
    graph[nume].next=heade[u];
    heade[u]=nume++;
}

void add_Q(int u,int v,int id){
    quary[numq].v=v;
    quary[numq].id=id;
    quary[numq].next=headq[u];
    headq[u]=numq++;
}

void input(){
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&a,&b,&c);
        add_E(a,b,c);
        add_E(b,a,c);
    }
    for(int i=1;i<=q;i++){
        scanf("%d%d",&a,&b);
        add_Q(a,b,i);
        add_Q(b,a,i);
    }
}

int Find(int x){ return x!=father[x] ? father[x]=Find(father[x]) : father[x]; }

void tarjan(int u){
    color[u]=1;
    vis[u]=true;
    for(int i=headq[u];i!=-1;i=quary[i].next){
        int ID=quary[i].id;
        if(ans[ID]!=-1) continue;
        int v=quary[i].v;
        if(color[v]==0) continue;
        if(color[v]==1) ans[ID]=depth[u]-depth[v];
        if(color[v]==2) ans[ID]=depth[u]+depth[v]-2*depth[Find(v)];
    }
    for(int i=heade[u];i!=-1;i=graph[i].next){
        int vv=graph[i].v;
        int dis=graph[i].dis;
        if(!vis[vv]){
            depth[vv]=depth[u]+dis;
            tarjan(vv);
            color[vv]=2;
            father[vv]=u;
        }
    }
}

void solve(){
    for(int i=1;i<=n;i++){
        if(!vis[i]){ memset(color,0,sizeof(color)); tarjan(i); }
    }
    for(int i=1;i<=q;i++){
        if(ans[i]==-1) printf("Not connected\n");
        else printf("%d\n",ans[i]);
    }
}

int main(){
    while(scanf("%d%d%d",&n,&m,&q)!=EOF){
        init();
        input();
        solve();
    }
    return 0;
}


 

你可能感兴趣的:(Algorithm,ACM,LCA,Tarjan,hihoCoder)