Codeforces Round #810 (Div. 2), problem: (B) Party

一.题意

你有n位同学,你想邀请他们中的一些人(可以都邀请上,也可以都不邀请)参加你的派对,他们之间有m对朋友关系(每个人可能有多个朋友)每对朋友会吃掉你的一块cake,但是你的厨师只能做出来偶数块cake,所以你的派对上只能出现偶数对朋友关系,所以你邀请到的人构成的朋友关系个数肯定是个偶数,这时候你可能就会不邀请班上的某些同学了,每位同学不被邀请的不开心值是ai,让你找到何种方案不开心值的和最小,求出这个不开心值的和,并输出。

输入:

T

n,m

a1~an

(然后下面是m对朋友关系)

输出:
最小的不开心值之和

二.思路

这个题里面含有一个小思维,首先我下了个结论,那就是作者要么排除0人要么排除1人要么排除2人不去邀请。

①排除0人:本来m就是偶数

②排除1人:m是奇数,这一个人所占有的朋友关系一定是奇数,这样m-这个人的朋友关系个数和 才是偶数。

③排除2人:m是奇数,这2个人每个人所占有的朋友关系一定是偶数(因为如果是奇数,那么他1个人就够了,不满足贪心思想),不但两人都是偶数,并且这两个人也要是朋友。这样去掉两人,去掉的朋友关系和才会是奇数(这里可以自己思考一下为什么)。

如果m是奇数,我们把①和②两种情况算出来的最小不开心值和再求个最小值就是最终答案,

具体实现方式看代码,有注释。

要是有更好的实现方式可以评论区call我OWO学习学习!

三.代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <map>
#include <vector>

using namespace std;

const int N = 1e5+10;
typedef pair<int, int> PII;
vector<int> v[N];
map<int,bool> st;
int a[N],cnt[N];
void solve()
{
    st.clear();
   int n,m;
   scanf("%d%d",&n,&m);
   
   for(int i=1;i<=n;i++)
   {
       scanf("%d",&a[i]);
       cnt[i]=0;
       v[i].clear();//清空vector O(n)时间复杂度
   }
   for(int i=1;i<=m;i++)
   {
       int a,b;
       scanf("%d%d",&a,&b);
        v[a].push_back(b);//朋友关系
        v[b].push_back(a);
       cnt[a]++;//cnt[i] i有几个朋友
       cnt[b]++;
   }
   if(m%2==0) 
   {
       puts("0");
       return;
   }
   int minone=0x3f3f3f3f;//情况①的最小不开心值
   for(int i=1;i<=n;i++)
   {
       if(cnt[i]&1)
       {
           st[i]=1;
           minone=min(a[i],minone);
       }
   }
   int mintwo=0x3f3f3f3f;//情况①的最小不开心值和
   for(int i=1;i<=n;i++)
   {
       st[i]=1;
       if(cnt[i]&1) continue;
       int siz=v[i].size();
       for(int j=0;j<siz;j++)//枚举当前枚举的i的所有朋友满足(情况②的第二个限制条件)
       {
           if(st[v[i][j]]) continue;
           if(cnt[v[i][j]]%2==0)
           {
               mintwo=min(a[i]+a[v[i][j]],mintwo);
           }
       }
   }
   cout<<min(mintwo,minone)<<endl;//①②取min
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        solve();
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值