C. Ehab and Path-etic MEXs
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a tree consisting of n nodes. You want to write some labels on the tree’s edges such that the following conditions hold:
Every label is an integer between 0 and n−2 inclusive.
All the written labels are distinct.
The largest value among MEX(u,v) over all pairs of nodes (u,v) is as small as possible.
Here, MEX(u,v) denotes the smallest non-negative integer that isn’t written on any edge on the unique simple path from node u to node v.
Input
The first line contains the integer n (2≤n≤105) — the number of nodes in the tree.
Each of the next n−1 lines contains two space-separated integers u and v (1≤u,v≤n) that mean there’s an edge between nodes u and v. It’s guaranteed that the given graph is a tree.
Output
Output n−1 integers. The ith of them will be the number written on the ith edge (in the input order).
Examples
inputCopy
3
1 2
1 3
outputCopy
0
1
inputCopy
6
1 2
1 3
2 4
2 5
5 6
outputCopy
0
3
2
4
1
題意:
給定n個點,n-1條邊,保證成樹,求所有<u,v>對所在的簡單路徑的MEX<u,v>的最大值最小。
tip:MEX指的是不在集合裏的最小非負正數,記得離散教過 ?
思路:
- 這道題我在比賽裏用了兩種寫法,可參考代碼1和代碼2。
- 一開始我的做法是從包含每個葉子節點的邊開始賦值,然後再去給不包含葉子結點的邊賦值。
- 那麼這樣如果只有兩個葉子結點,說明整張圖是一條鏈,那麼怎麼賦值都是無所謂的;而如果葉子結點的數目大於2,那麼不論選哪兩片葉子,都會有另一片葉子不在這條路徑裏面,也就是MEX<u,v><=2。
- 然後這個思路的話就需要特判 2 2 1 這種情況,處理好了就能AC。
- 由於在最後心神不寧,就把C給重寫了,換了一個差不多的思路:
- 在所有點中找出度大於2的點,把這個點相接的三條邊賦值爲0/1/2,那麼這樣無論取哪兩個點都可以保證MEX<u,v> <=2 ;而如果沒有度大於2,那麼說明整張圖是一條鏈,那麼情況和上面就相同了。
- 如果有什麼講的不清楚的歡迎留言私信交流~
代碼1:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}ll Inv(ll x,ll p){return qp(x,p-2,p);}
ll Cal(ll n,ll m,ll p){if (m>n) return 0;ll ans = 1;for(int i = 1; i <= m; ++i)
ans=ans*Inv(i,p)%p*(n-i+1)%p;return ans%p;}
const int manx=2e5+5;
struct node{
ll v,next,u;
}a[manx*2];
ll head[manx],d[manx],k,cnt[manx];
void add(ll u,ll v){
a[++k].v=v,a[k].next=head[u],head[u]=k,a[k].u=u;
}
int main(){
ll n=read(),u,v;
for(int i=1;i<n;i++){
u=read(),v=read();
add(u,v);
d[v]++,d[u]++;
}
ll root,q=0,ans;
memset(cnt,inf,sizeof(cnt));
for(int i=1;i<=n;i++)
if(d[i]==1) cnt[i]=q++;
for(int i=1;i<n;i++){
ll u=a[i].u,v=a[i].v;
if(d[u]==1&&d[u]==1) ans=min(cnt[v],cnt[u]);
else if(d[v]==1) ans=cnt[v];
else if(d[u]==1) ans=cnt[u];
else ans=q++;
printf("%lld\n",ans);
}
return 0;
}
代碼2:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}ll Inv(ll x,ll p){return qp(x,p-2,p);}
ll Cal(ll n,ll m,ll p){if (m>n) return 0;ll ans = 1;for(int i = 1; i <= m; ++i)
ans=ans*Inv(i,p)%p*(n-i+1)%p;return ans%p;}
const int manx=2e5+5;
ll u[manx],v[manx],d[manx];
int main(){
ll n=read();
for(int i=1;i<n;i++){
u[i]=read(),v[i]=read();
d[v[i]]++,d[u[i]]++;
}
ll root=0,q=0,ans;
for(int i=1;i<=n;i++)
if(d[i]>=3){
root=i;
break;
}
if(!root){
for(ll i=1;i<n;i++)
printf("%lld\n",i-1);
}
else{
ll cnt=0,x=3;
for(int i=1;i<n;i++){
if( (root==u[i]||root==v[i]) && cnt<3 ){
printf("%lld\n",cnt++);
}
else printf("%lld\n",x++);
}
}
return 0;
}