Codeforces 1325 C. Ehab and Path-etic MEXs (思維) /詳解

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. 這道題我在比賽裏用了兩種寫法,可參考代碼1和代碼2。
  2. 一開始我的做法是從包含每個葉子節點的邊開始賦值,然後再去給不包含葉子結點的邊賦值。
  3. 那麼這樣如果只有兩個葉子結點,說明整張圖是一條鏈,那麼怎麼賦值都是無所謂的;而如果葉子結點的數目大於2,那麼不論選哪兩片葉子,都會有另一片葉子不在這條路徑裏面,也就是MEX<u,v><=2。
  4. 然後這個思路的話就需要特判 2 2 1 這種情況,處理好了就能AC。
  5. 由於在最後心神不寧,就把C給重寫了,換了一個差不多的思路:
  6. 在所有點中找出度大於2的點,把這個點相接的三條邊賦值爲0/1/2,那麼這樣無論取哪兩個點都可以保證MEX<u,v> <=2 ;而如果沒有度大於2,那麼說明整張圖是一條鏈,那麼情況和上面就相同了。
  7. 如果有什麼講的不清楚的歡迎留言私信交流~

代碼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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章