(dfs)codeforces 767C - Garland
题意:
一棵树,每个节点有一个权值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\n",*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\n",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\n",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; }