cf1627 Round #766 Div2-C【图论+DFS】

Date:2022.01.17
题意:给定一个树,给每个边加权能不能构造出任意<=2个边相加都是质数。能输出对应边的方案,不能输出-1。
在这里插入图片描述
思路:首先单独一个边是质数很好办,每个边都是质数即可。在此前提下,怎么才能保证每两个边相加都是质数?不难发现,一旦存在度数>=3的点就不能满足,因为质数只有偶质数2和奇质数,任意两个奇数相加为偶数且一定是合数,只有一个奇质数和一个偶质数相加才能保证和为质数,因此不存在任意一个点连着三条边且这三条边两两加和都为质数的情况。由此,每个点的度数只能<=2,又是树,满足情况的只能是单链。建个图,dfs每次给边权依次赋值2、3,每次顺序记录边,输出再离线做一下。
代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
const int N = 2e5+10;//注意点最多为边的两倍,多开一倍
typedef long long LL;
typedef pair<int, int> PII;
map<PII,LL>q;set<LL>s;
LL a[N],b[N];
LL d[N],h[N],idx,e[N],ne[N];
bool st[N];
LL n,m,t,k;
void add(LL a,LL b)
{
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
void dfs(LL a,LL ans,LL idx)
{
    if(idx==s.size()) return;
    st[a]=true;
    //cout<<a<<' ';
    for(int i=h[a];i!=-1;i=ne[i])
    {
        if(st[e[i]]) continue;
        PII t1={a,e[i]},t2={e[i],a};
        q[t1]=ans;q[t2]=ans;
        if(ans==2) dfs(e[i],3,idx+1);
        else if(ans==3) dfs(e[i],2,idx+1);
    }
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        bool flag=true;
        memset(d,0,sizeof d);memset(h,-1,sizeof h);memset(st,0,sizeof st);
        q.clear();s.clear();
        cin>>n;
        for(int i=1;i<=n-1;i++)
        {
            cin>>m>>k;a[i]=m;b[i]=k;
            d[m]++;d[k]++;s.insert(m);s.insert(k);
            add(m,k);add(k,m);
        }
        for(auto it:s) 
            if(d[it]>2) {flag=false;break;}
        if(!flag) {cout<<"-1"<<endl;continue;}
        else
        {
            for(auto it:s)
                if(d[it]==1) {dfs(it,2,0);break;}
            for(int i=1;i<=n-1;i++)
            {
                PII t={a[i],b[i]};
                cout<<q[t]<<' ';
            }
            cout<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值