题意:给你n种物品,有m种限制条件,然后输入n种物品的价值,m种限制条件,表示第i个物品不能与第j个物品分成一组,求把物品分成两组后,价值差最小,输出其中最大的价值。
思路:对于每一个限制条件,都可以看成一棵树,我们对这棵树染色,分成两组,然后把每一组都取上,输出答案。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
vector<int>G[205];
int a[205],c[205],val[3];
bitset<maxn> d[2];
void dfs(int u) //染色
{
val[c[u]]+=a[u];
for(auto v : G[u])
{
if(!c[v])
{
c[v]=3-c[u];
dfs(v);
}
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
d[0].reset(); //把 bitset 置0;
int n,m,sum=0;
cin>>n>>m;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
cin>>a[i];
G[i].clear();
a[i]/=100; //题目数据说是整百的
sum+=a[i];
}
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
int cur=0;
d[0][0]=1;
for(int i=1;i<=n;i++)
{
val[1]=val[2]=0; //对一个二分图染色
if(!c[i])
{
c[i]=1;
dfs(i);
cur^=1; // 滚动数组,因为当前状态只由前一个状态转移
d[cur]=d[!cur];
d[cur]|=(d[!cur]<<val[1]);
d[cur]|=(d[!cur]<<val[2]);
}
}
int ans;
for(int i=sum/2;i>0;i--)
{
if(d[cur][i])
{
ans=sum-i;
cout<<ans*100<<'\n';
break;
}
}
}
}
tips:举例:假设你申明一个bitset<50>d,d[0]=1,d[1]=0,d[2]=1,d[3]=1; 那么d<<1,那么变成的d[0]=0,d[1]=1,d[2]=0,d[3]=1,d[4]=1;
来源:CSDN
作者:嘻嘻嘻西
链接:https://blog.csdn.net/weixin_44499508/article/details/103245170