(dfs)codeforces 767C

题意:

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

分析:

先可以先算出总大小sum。

接着%3看能不能分,不能-1,能继续。

然后递归算出每个子树的权值和。

一开始想到直接找出两个sum/3就行了,后来发现还会可能有两个分点输出祖辈关系。

想到半天,感觉很容易dfs写,,,,然而想了半天不知道怎么写,,好久不写题,自己好辣鸡- -

后来想到一种方法,一开始记录好每个节点的父节点,先找出所有的sum/3扔到set里,然后从每个sum/3节点出发向上找,一旦找到sum/3*2即可,如果遇到sum/3,就把它去掉,如果没找到sum/3*2,就看最后留下的sum/3有几个,如果大于等于2,就输出前两个,否则-1,中间如果怕超时,加个bool数组记录一下,这样也只是把所有点扫一遍而已。

其实更简单的方法是直接两次dfs,第一找出来一个sum/3,然后子树结果清零,然后再dfs一次,直接忽视掉前一个sum/3,找出第二个sum/3,如果能找出来就输出,不能就-1。

唉,感觉自己思维江化了。

代码(两种思路,第二种最简单了,,):

  1 #include <set>
  2 #include <map>
  3 #include <list>
  4 #include <cmath>
  5 #include <queue>
  6 #include <vector>
  7 #include <bitset>
  8 #include <string>
  9 #include <cctype>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <iostream>
 14 #include <algorithm>
 15 
 16 using namespace std;
 17 
 18 typedef long long ll;
 19 typedef unsigned long long ull;
 20 #define inf (0x3f3f3f3f)
 21 #define lnf (0x3f3f3f3f3f3f3f3f)
 22 #define eps (1e-6)
 23 int sgn(double a) {
 24     return a < -eps ? -1 : a < eps ? 0 : 1;
 25 }
 26 
 27 //--------------------------
 28 
 29 const int maxn = 1000010;
 30 
 31 
 32 set<int> ans;
 33 vector<int> v[maxn];
 34 int tem[maxn];
 35 int par[maxn];
 36 bool vis[maxn];
 37 int n;
 38 int s;
 39 
 40 bool dfs(int u) {
 41     for(int i=0; i<v[u].size(); i++) {
 42         dfs(v[u][i]);
 43         tem[u]+=tem[v[u][i]];
 44     }
 45 }
 46 
 47 int dfs2(int u) {
 48     if(u==s||vis[u])return -1;
 49     vis[u]=true;
 50     if(tem[u]==tem[s]/3*2) {
 51         return u;
 52     }
 53     if(tem[u]==tem[s]/3) {
 54         ans.erase(u);
 55     }
 56     dfs2(par[u]);
 57 }
 58 
 59 
 60 
 61 void solve() {
 62     scanf("%d",&n);
 63     int u,t;
 64     memset(vis,0,sizeof(vis));
 65     for(int i=1; i<=n; i++) {
 66         scanf("%d%d",&u,&t);
 67         par[i]=u;
 68         if(u!=0) {
 69             v[u].push_back(i);
 70         } else {
 71             s=i;
 72         }
 73         tem[i]=t;
 74     }
 75     dfs(s);
 76     if(tem[s]%3==0) {
 77         for(int i=1; i<=n; i++) {
 78             if(i==s)continue;
 79             if(tem[i]==tem[s]/3)ans.insert(i);
 80         }
 81         for(set<int>::iterator it=ans.begin(); it!=ans.end(); it++) {
 82             int res=dfs2(par[*it]);
 83             if(res!=-1) {
 84                 printf("%d %d
",*it,res);
 85                 return;
 86             }
 87         }
 88         if(ans.size()>=2) {
 89             set<int>::iterator ita=ans.begin();
 90             int a=*ita;
 91             ita++;
 92             int b=*ita;
 93             printf("%d %d
",a,b);
 94         } else {
 95             puts("-1");
 96         }
 97     } else {
 98         puts("-1");
 99     }
100 }
101 
102 int main() {
103 
104 #ifndef ONLINE_JUDGE
105     freopen("1.in", "r", stdin);
106     //freopen("1.out", "w", stdout);
107 #endif
108     //iostream::sync_with_stdio(false);
109     solve();
110     return 0;
111 }
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <vector>
#include <bitset>
#include <string>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define inf (0x3f3f3f3f)
#define lnf (0x3f3f3f3f3f3f3f3f)
#define eps (1e-6)
int sgn(double a) {
    return a < -eps ? -1 : a < eps ? 0 : 1;
}

//--------------------------

const int maxn = 1000010;


vector<int> v[maxn];
int tem1[maxn],tem2[maxn];
int sum;
int n;
int s;
bool flag1,flag2;
int res1,res2;

void dfs(int u) {
    for(int i=0; i<v[u].size(); i++) {
        dfs(v[u][i]);
        if(flag1)return ;
        tem1[u]+=tem1[v[u][i]];
    }
    if(u!=s&&tem1[u]==sum/3) {
        flag1=true;
        res1=u;
    }
}

void dfs2(int u) {
    for(int i=0; i<v[u].size(); i++) {
        if(flag1&&v[u][i]==res1) {
            continue;
        }
        dfs2(v[u][i]);
        if(flag2)return ;
        tem2[u]+=tem2[v[u][i]];
    }
    if(u!=s&&tem2[u]==sum/3) {
        flag2=true;
        res2=u;
    }
}



void solve() {
    scanf("%d",&n);
    int u,t;
    sum=0;
    flag1=flag2=false;
    for(int i=1; i<=n; i++) {
        scanf("%d%d",&u,&t);
        if(u!=0) {
            v[u].push_back(i);
        } else {
            s=i;
        }
        tem1[i]=tem2[i]=t;
        sum+=t;
    }
    if(sum%3!=0) {
        puts("-1");
        return;
    }
    dfs(s);
    if(!flag1) {
        puts("-1");
        return;
    }
    dfs2(s);
    if(!flag2) {
        puts("-1");
        return;
    } else {
        printf("%d %d
",res1,res2);
    }

}

int main() {

#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    //freopen("1.out", "w", stdout);
#endif
    //iostream::sync_with_stdio(false);
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/tak-fate/p/6423768.html