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;
}
发布了79 篇原创文章 · 获赞 45 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/JiangHxin/article/details/104872444
今日推荐