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;
}
原文地址:https://www.cnblogs.com/yxg123123/p/7241522.html