第一次刷CF的比赛,刚开始还是有点小紧张呢……结果第一题花了40min,最后手一抖数组开小了一位,Final Test RE,然后改的时候还改了半天 (╯‵□′)╯︵┻━┻ 第二题反而只花了20+min 第三题想的有点久,其实代码和思路都比较简单
详细题解:
T1:想怎么写怎么些
T2:把1~lim中所有数的lowbit处理一下存起来,然后构造答案。另外可以发现只要Σlowbit(i)>=sum就一定有解,至于证明和多重背包的二进制分解差不多。至于方案随便构造一个就行了,反正是SPJ
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int N_MAX=30;
vector<int> pwr[N_MAX],res;
int N,M;
namespace Nwork{
int lowbit(int x){
int ret=1;
for (int i=0; i<=17; ++i,ret*=2)
if (x&(1<<i)) break;
return int(log2(ret))+1;
}
void main(){
int sum=0;
for (int i=1; i<=M; ++i){
int low=lowbit(i); sum+=low;
pwr[low].push_back(i);
}
if (N>sum){ printf("-1\n");return; }
for (int i=20; i>=1; --i){
if (!N) break;
for (int j=0,size=pwr[i].size(); N>=i && j<size; ++j){
res.push_back(pwr[i][j]);
N-=i;
}<pre name="code" class="cpp">
T3:把删除所有点转化为删除所有边,权值取端点中的最小值即可
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int N_MAX=2000+10;
int N,M,ans,v[N_MAX];
int main(){
scanf("%d%d", &N, &M);
for (int i=1;i<=N;++i)
<span style="white-space:pre"> </span>scanf("%d", &v[i]);
for (int i=1;i<=M;++i){
int a,b; scanf("%d%d", &a, &b);
if (v[a]>v[b]) ans+=v[b]; else ans+=v[a];
}
printf("%d\n",ans);
return 0;
}