题意
给定一颗包含 n n n个节点的树,添加权值使得任意两点的简单路径的长度最大值最小,权值范围 [ 0 , n − 2 ] [0,n-2] [0,n−2]。
输入描述
第一行一个 n n n表示树节点的个数
接下来 n − 1 n-1 n−1行,每行两个数 u , v u,v u,v,表示u和v存在一条边.
输入保证是一颗树, 2 ≤ n ≤ 1 0 5 2 \leq n\leq 10^5 2≤n≤105.
输出描述
输出 n − 1 n-1 n−1行,每一行代表的是第 i i i行输入边所对应的权值,答案可能存在多种,输出任意一种即可。
分析
考虑贪心,尽可能把权值小的数放在叶子节点所对应的边,故对所对应简单路径的长度最大的才会最小。换句话说就是尽可能的将权值大的数放在任意两点简单路径,经过的边较多的地方。
#include <bits/stdc++.h>
#define fir first
#define sec second
#define pb push_back
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int maxn=1e6+7;
ll a[maxn],b[maxn],ans[maxn];
ll n,m;
int solve(int T) {
memset(a,0,sizeof(a));
int n;cin>>n;
vector<pair<int,int> >vec;
for(int i=1;i<=n-1;i++){
int x,y;cin>>x>>y;
a[x]++;a[y]++;
vec.pb({x,y});
}
memset(ans,-1,sizeof(ans));
memset(b,0,sizeof(b));
int now=0;
for(int i=0;i<n-1;i++){
if(a[vec[i].fir]==1&&b[vec[i].fir]==0) {
ans[i]=now++;
b[vec[i].fir]==1;
}
else if(a[vec[i].sec]==1&&b[vec[i].sec]==0) {
ans[i]=now++;
b[vec[i].sec]==1;
}
}
for(int i=0;i<n-1;i++) if(ans[i]==-1) ans[i]=now++;
for(int i=0;i<n-1;i++) cout<<ans[i]<<endl;
return 0;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
// cin>>T;
for(int cas=1; cas<=T; cas++) {
solve(T);
}
return 0;
}
题意
给定两个数 0 ≤ u , v ≤ 1 0 18 0 \leq u,v\leq10^{18} 0≤u,v≤1018,寻找最短的数组使得其满足数组的每个元素的异或值等于 u u u,和为 v v v。
输入描述
输入两个数 0 ≤ u , v ≤ 1 0 18 0 \leq u,v\leq10^{18} 0≤u,v≤1018.
输出描述
答案不存在,则输出 − 1 -1 −1.
答案存在,则第一行输出数组元素的个数,第二行输出n个整数。
分析
若答案存在的话,构造得 [ u , x , x ] , x = v − u 2 [u,x,x],x=\frac{v-u}{2} [u,x,x],x=2v−u满足题意,故数组最大长度为3
- 考虑答案不存在的情况,由于异或是某种不进位的加法,存在 u > v u>v u>v或者 u u u, v v v奇偶性不同,则输出 − 1 -1 −1。
- 考虑长度 0 , 1 0,1 0,1的情况,当 u = v u=v u=v时,输出 1 1 1, u = v = 0 u=v=0 u=v=0时,输出 0 0 0.
- 考虑长度为 2 , 3 2,3 2,3的情况。如果存在 < a , b > <a,b> <a,b>满足条件,则有
a ⊕ b = u , a + b = v a \oplus b =u,a+b=v a⊕b=u,a+b=v注意到 a + b = a ⊕ b + 2 ∗ ( a & b ) a+b=a\oplus b+2*(a&b) a+b=a⊕b+2∗(a&b).
得 a & b = v − u 2 = x a&b=\frac{v-u}{2}=x a&b=2v−u=x
如果 x x x某一位存在1 的话,那么说明 a , b a,b a,b中对应位也一定是1,那么我们可以得到 a ⊕ b = u a \oplus b=u a⊕b=u对应位必定是0,换句话说就是,当长度为2时,必须得满足 x & u = 0 x&u=0 x&u=0
也就意味着 x ⊕ u = x + u x\oplus u=x+u x⊕u=x+u
故长度为2的数组对应为 [ u + x , x ] [u+x,x] [u+x,x],长度为3的数组对应为 [ u , x , x ] [u,x,x] [u,x,x]
代码
#include <bits/stdc++.h>
#define fir first
#define sec second
#define pb push_back
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int maxn=1e6+7;
ll a[maxn],b[maxn],ans[maxn];
ll n,m;
int solve(int T) {
ll u,v;cin>>u>>v;
if(u==0&&v==0) cout<<0<<endl;
else if(u==v) cout<<1<<endl<<u<<endl;
else if(u>v||(v-u)%2) cout<<-1<<endl;
else {
ll x=(v-u)/2;
if((x&u)==0) cout<<2<<endl<<x<<" "<<(x^u)<<endl;
else cout<<3<<endl<<u<<" "<<x<<" "<<x<<endl;
}
return 0;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
// cin>>T;
for(int cas=1; cas<=T; cas++) {
solve(T);
}
return 0;
}