HDU 5044——Tree

来源:互联网 发布:宿舍楼网络规划 编辑:程序博客网 时间:2024/06/05 18:45

题意:两种操作,在点上面加权值或在边上面加权值,m次操作以后为每条边和每个点分别权值多少。
思路:LCA。这道题不知道为什么,提交的时候一直超时,然后上网找了kuangbin的标程也超时了。。。只有这个博客里的代码能过。http://blog.csdn.net/zz_1215/article/details/39649687
代码看了北大写的,然后自己写了一篇,到现在还没过。。

#include<cstdio>#include<cstdlib>#include<iostream>#include<cstring>#include<map>#include<set>#include<list>#include<stack>#include<algorithm>#include<queue>#include<vector>#include<time.h>#include<iomanip>#include<assert.h>using namespace std;const int maxn = 100005;struct Edge{    int u,v;    int next;    int id;}edge[maxn*2];int tot ;int first[maxn];void add(int uu,int vv,int id){    edge[tot].u = uu;    edge[tot].v = vv;    edge[tot].id = id;    edge[tot].next = first[uu];    first[uu] = tot++;}int n,m;int dep[maxn];int pre[maxn];int dp[17][maxn];int q[maxn],qh,qt;int recE[maxn];int recN[maxn];void bfs(int u) {    qh = qt = 0;    q[qt ++] = u;    for (int j = 0; j < 17; ++ j) dp[j][0] = -1;    dep[u] = 0;    pre[u] = -1;    while (qh != qt) {        u = q[qh ++];        for (int now = first[u], v; now != -1; now = edge[now].next)            if (dp[0][u] != (v = edge[now].v)) {                dp[0][v] = u;                for (int j = 1; j < 17; ++ j) {                    if (dp[j - 1][v] == -1) {                        dp[j][v] = -1;                    } else {                        dp[j][v] = dp[j - 1][dp[j - 1][v]];                    }                }                q[qt ++] = v;                dep[v] = dep[u] + 1;                pre[v] = edge[now].id;            }    }}int lca(int u, int v) {    if (dep[u] < dep[v]) swap(u, v);    int del = dep[u] - dep[v];    for (int j = 16; j >= 0; -- j)        if (del >> j & 1) u = dp[j][u];    for (int j = 16; j >= 0; -- j)        if (dp[j][u] != dp[j][v]) {            u = dp[j][u];            v = dp[j][v];        }    if (u != v) u = dp[0][u];    return u;}inline bool scan_d(int &ret){    char c;int sgn;    if(c = getchar(),c == EOF)return 0;    while(c!='-' && (c<'0'||c>'9'))c = getchar();    sgn = (c == '-')?-1:1;    ret = (c == '-')?0 :c-'0';    while(c = getchar(),c>='0'&&c<='9')ret = ret*10 + (c-'0');    ret *=sgn;    return 1;}int col[maxn];void putint(int x){    if(x<0){putchar('-'); x *= -1;}    if(x == 0){        putchar('0');        return;    }    char s[20];    int cur = 0;    while(x!=0){        s[cur++] = '0' + x%10;        x/=10;    }    for(int i = cur-1;i>=0;i--){        putchar(s[i]);    }}void solve(){    for(int i = qt-1; i>=0;--i){        int u = q[i];        if(dp[0][u] != -1){            recE[dp[0][u]] += recE[u];            recN[dp[0][u]] += recN[u];        }    }    for(int i = 1;i<n;++i)col[pre[i]] = recE[i];    for(int i = 0; i < n; ++i){        if(i)printf(" ");//        printf("%d",recN[i]);        putint(recN[i]);    }    puts("");    for(int i = 0; i < n-1 ; ++i){        if(i)printf(" ");//        printf("%d",col[i]);        putint(col[i]);    }    puts("");}int main(){//    freopen("data.txt","r",stdin);    int T;    scan_d(T);    int kase = 0;    while(T -- ){        printf("Case #%d:\n",++kase);        tot = 0;memset(first,-1,sizeof(first));        scan_d(n);scan_d(m);        for(int i = 0; i < n-1;++i){            int u,v;            scan_d(u);scan_d(v);            u--;v--;            add(u,v,i);            add(v,u,i);        }        dep[0] = 0;        pre[0] = -1;        bfs(0);        memset(recE,0,sizeof(recE));        memset(recN,0,sizeof(recN));        for(int i = 0; i < m; ++i){            int cmd;            int u,v,k;            scan_d(cmd);            scan_d(u);scan_d(v);scan_d(k);            u--;v--;            int p = lca(u,v);            if(cmd == 1){                recN[u] += k;                recN[v] += k;                recN[p] -= k;                if(dp[0][p] != -1)recN[dp[0][p]] -= k;            } else {                recE[u] += k;                recE[v] += k;                recE[p] -= k*2;            }        }        solve();    }    return 0;}
0 0