zoj 3195 Design the city

来源:互联网 发布:女士牛仔裤品牌 知乎 编辑:程序博客网 时间:2024/05/01 21:57

题意:找无向树上三个点间的距离

题解:在线lca,开始是想分情况讨论,后来发现可以通过求3对两点间距离除以2来求得答案,感觉是一种尝试将问

题规模变小的思想吧。

总结:这个题因为小错改了好久好久才改出来,以后规定自己纯改错时间不得超过20分钟!

下面贴出两种lca转rmq的实现方法

#include<iostream>#include<cstring>#include<cstdio>#include<vector>using namespace std;typedef pair<int,int>pii;#define MAXN 151000#define LOG 20int rmq[MAXN][LOG],s[MAXN],place[MAXN],id[MAXN],deep[MAXN];int cnt,vs;vector<pii>vec[MAXN];void dfs(int u,int fa,int val){    for(int i = 0;i < vec[u].size();i++)    {        int v = vec[u][i].first,w = vec[u][i].second;        if(v == fa)continue;        s[v] = val + w;        id[++cnt] = v;        rmq[++vs][0] = cnt;        place[v] = vs;        dfs(v,u,val + w);        rmq[++vs][0] = rmq[place[u]][0];    }}void init_rmq(){    for(int j = 1;(1 << j) <= vs + 1;j++)        for(int i = 0;i <= vs;i++)            rmq[i][j] = min(rmq[i][j - 1],rmq[i + (1 << (j - 1))][j - 1]);}int query(int a,int b){    a = place[a],b = place[b];    if(a > b)swap(a,b);    int len = -1;    while(b - a + 1 >= (1 << (len + 1)))        len++;    return id[min(rmq[a][len],rmq[b - (1 << len) + 1][len])];}int main(){    int n,u,v,w,_ = 0,q;    while(scanf("%d",&n) != EOF)    {        if(_++)puts("");        for(int i = 0;i < n;i++)vec[i].clear();        for(int i = 1;i < n;i++)        {            scanf("%d%d%d",&u,&v,&w);            vec[u].push_back(pii(v,w));            vec[v].push_back(pii(u,w));        }        cnt = vs = 0;        dfs(0,-1,0);        init_rmq();        scanf("%d",&q);        while(q--)        {            scanf("%d%d%d",&u,&v,&w);            int ans1 = s[u] + s[v] - (s[query(u,v)] << 1);            int ans2 = s[u] + s[w] - (s[query(u,w)] << 1);            int ans3 = s[v] + s[w] - (s[query(v,w)] << 1);            printf("%d\n",(ans1 + ans2 + ans3) >> 1);        }    }}




#include<iostream>#include<cstring>#include<cstdio>#include<vector>using namespace std;typedef pair<int,int>pii;#define MAXN 151000#define LOG 20int rmq[MAXN][LOG],s[MAXN],place[MAXN],deep[MAXN];int cnt,vs;vector<pii>vec[MAXN];void dfs(int u,int fa,int d,int val){    for(int i = 0;i < vec[u].size();i++)    {        int v = vec[u][i].first,w = vec[u][i].second;        if(v == fa)continue;        deep[v] = d;        s[v] = val + w;        rmq[++vs][0] = v;        place[v] = vs;        dfs(v,u,d + 1,val + w);        rmq[++vs][0] = u;    }}void init_rmq(){    for(int j = 1;(1 << j) <= vs + 1;j++)        for(int i = 0;i <= vs;i++)        {            int d1 = deep[rmq[i][j - 1]];            int d2 = deep[rmq[i + (1 << (j - 1))][j - 1]];            if(d1 < d2)rmq[i][j] = rmq[i][j - 1];            else rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1];        }}int query(int a,int b){    a = place[a],b = place[b];    if(a > b)swap(a,b);    int len = -1;    while(b - a + 1 >= (1 << (len + 1)))        len++;    int d1 = deep[rmq[a][len]];    int d2 = deep[rmq[b - (1 << len) + 1][len]];    if(d1 < d2)return rmq[a][len];    else return rmq[b - (1 << len) + 1][len];}int main(){    int n,u,v,w,_ = 0,q;    while(scanf("%d",&n) != EOF)    {        if(_++)puts("");        for(int i = 0;i < n;i++)vec[i].clear();        for(int i = 1;i < n;i++)        {            scanf("%d%d%d",&u,&v,&w);            vec[u].push_back(pii(v,w));            vec[v].push_back(pii(u,w));        }        cnt = vs = 0;        dfs(0,-1,1,0);        init_rmq();        scanf("%d",&q);        while(q--)        {            scanf("%d%d%d",&u,&v,&w);            int ans1 = s[u] + s[v] - (s[query(u,v)] << 1);            int ans2 = s[u] + s[w] - (s[query(u,w)] << 1);            int ans3 = s[v] + s[w] - (s[query(v,w)] << 1);            printf("%d\n",(ans1 + ans2 + ans3) / 2);        }    }}


0 0
原创粉丝点击