• Codeforces 767C. Garland (dfs)


    题目链接:

    http://codeforces.com/problemset/problem/767/C

    题意:

    一棵树,每个节点有一个权值t,把它分成三部分,每部分要求权值和相等。

    思路:

    由于子树的子树里再出现等于sum/3的情况,那么dp[u]=0,就可以很好的避免计算情况了

    dfs  第一找出来一个sum/3,然后子树结果清零,然后再dfs一次,直接忽视掉前一个sum/3,找出第二个sum/3,如果能找出来就输出,不能就-1。

    还有一种笨写法。(傻逼的我调了半辈子)

    代码:

    代码一:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 1e5+10;
    
    int n,s,x,dp[maxn],ans1,ans2,sum;
    vector<int> g[maxn];
    
    void dfs(int u){
        for(int i=0; i<(int)g[u].size(); i++){
            dfs(g[u][i]);
            dp[u] += dp[g[u][i]];
        }
        if(dp[u]==sum/3 && u!=s){
            if(!ans1) { ans1=u; dp[u]=0;}
            else if(!ans2) { ans2=u; return ;}
        }
    }
    
    int main()
    {
        cin >> n;
        sum = 0;
        for(int i=1; i<=n; i++){
            scanf("%d%d",&x,&dp[i]);
            if(x==0) s = i;
            else g[x].push_back(i);
            sum += dp[i];
        }
        if(sum%3) return puts("-1"),0;
    
        dfs(s);
        if(!ans1 || !ans2) return puts("-1"),0;
        else cout<<ans1<<" "<<ans2<<endl;
    
        return 0;
    }

    代码二:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 1e6+10;
    int n;
    vector<int> mp[maxn];
    int vis[maxn];
    int val[maxn];
    int v[maxn];
    int avg;
    int ans1,ans2,s;
    
    //int tem1[maxn],tem2[maxn];
    //bool flag1,flag2;
    
    int dfs1(int st){
        if(vis[st] || st==ans1)
            return 0;
        vis[st]=1;
        val[st]=v[st];
        for(int i=0; i<(int)mp[st].size(); i++){
            int u = mp[st][i];
            if(u == ans1) continue;
            val[st]+=dfs1(u);
        }
        return val[st];
    }
    
    void dfs2(int st){
        if(ans1 != 0) return ;
        for(int i=0; i<(int)mp[st].size(); i++){
            dfs2(mp[st][i]);
            if(ans2 != 0) return ;
        }
        if(ans1==0 && val[st]==avg && st!=s)
            ans1 = st;
    }
    
    void dfs3(int st){
        if(ans2 != 0) return ;
        for(int i=0; i<(int)mp[st].size(); i++){
            if(mp[st][i]==ans1) continue;
            dfs3(mp[st][i]);
            if(ans2 != 0) return ;
        }
        if(ans2==0 && val[st]==avg && st!=s && st!=ans1)
            ans2 = st;
    }
    //void dfs2(int u) {
    //    for(int i=0; i<mp[u].size(); i++) {
    //        dfs2(mp[u][i]);
    //        if(flag1)return ;
    //        tem1[u]+=tem1[mp[u][i]];
    //    }
    //    if(u!=s&&tem1[u]==avg) {
    //        flag1=true;
    //        ans1=u;
    //    }
    //}
    //
    //void dfs3(int u) {
    //    for(int i=0; i<mp[u].size(); i++) {
    //        if(flag1&&mp[u][i]==ans1) {
    //            continue;
    //        }
    //        dfs3(mp[u][i]);
    //        if(flag2)return ;
    //        tem2[u]+=tem2[mp[u][i]];
    //    }
    //    if(u!=s&&tem2[u]==avg) {
    //        flag2=true;
    //        ans2=u;
    //    }
    //}
    
    int main()
    {
        cin >> n;
        for(int x,val,i=1;i<=n;i++){
            scanf("%d%d",&x,&v[i]);
    //        tem1[i] = tem2[i] = v[i];
            if(x == 0) s = i;
            else mp[x].push_back(i);
        }
        dfs1(s);
        avg=val[s]/3;
        if(val[s]%3){
            cout << -1 << endl;
            return 0;
        }
        dfs2(s);
        if(ans1==0) return puts("-1"),0;
        memset(vis,0,sizeof(vis));
        dfs1(s);
        dfs3(s);
        if(ans2==0) return puts("-1"),0;
        cout << ans1 << " " << ans2 << endl;
    }
  • 相关阅读:
    P1410 子序列 (动态规划)
    P2085 最小函数值 (堆)
    [ZJOI2007]棋盘制作 (单调栈,动态规划)
    [ZJOI2005]午餐 (贪心,动态规划)
    黑匣子_NOI导刊2010提高 (对顶堆)
    [BZOJ1455] 罗马游戏 (左偏树||并查集)
    P1651 塔 (动态规划)
    两类斯特林数 (组合数学)
    从编程到工程
    失败的过程也是过程
  • 原文地址:https://www.cnblogs.com/yxg123123/p/7241522.html
Copyright © 2020-2023  润新知