西安区域赛 D.Miku and Generals 二分图+背包

Miku and Generals

Describe

“Miku is matchless in the world!” As everyone knows, Nakano Miku is interested in Japanese generals, so Fuutaro always plays a kind of card game about generals with her. In this game, the players pick up cards with generals, but some generals have contradictions and cannot be in the same side. Every general has a certain value of attack power (can be exactly divided by (100) ), and the player with higher sum of values will win. In this game all the cards should be picked up.

This day Miku wants to play this game again. However, Fuutaro is busy preparing an exam, so he decides to secretly control the game and decide each card's owner. He wants Miku to win this game so he won't always be bothered, and the difference between their value should be as small as possible. To make Miku happy, if they have the same sum of values, Miku will win. He must get a plan immediately and calculate it to meet the above requirements, how much attack value will Miku have?

As we all know, when Miku shows her loveliness, Fuutaro's IQ will become (0) . So please help him figure out the answer right now!

Input

Each test file contains several test cases. In each test file:

The first line contains a single integer (T(1 le T le 10))which is the number of test cases.

For each test case, the first line contains two integers: the number of generals (N(2 le N le 200))and thenumber of pairs of generals that have contradictions⁡ (M(0 le M le 200)).

The second line contains (N) integers, and the iii-th integer is (c_i), which is the attack power value of the iii-th general ((0 le c_i le 5 imes 10^4)).

The following (M) lines describe the contradictions among generals. Each line contains two integers AAA and BBB , which means general AAA and BBB cannot be on the same side ((1 le A , B le N)).

The input data guarantees that the solution exists.

Output

For each test case, you should print one line with your answer.

Hint

In sample test case, Miku will get general 2 and 3 .

样例输入

1
4 2
1400 700 2100 900
1 3
3 4

样例输出

2800

题意

给你n个数,把他们分成两组使得差值最小,求较大那组权值和。有些数不能在一起,保证有解。

题解

先二分图染色,也可以并查集(我考场用并查集写的,结果WA到结束,所以对并查集产生了阴影qwq)。

然后就是一个比较裸的可行性背包,背包容量为sum/2。

如果不会背包,可以先做这道相似的背包题:https://www.luogu.org/problemnew/show/P1282

(我一开始统计方案数,一直WA,原来是方案数报爆int 了,真是伤心,还是fwl大佬看出来的)

代码

#include<bits/stdc++.h>
using namespace std;
#define N 205
#define M 205
#define V 50050
int n,m,a[N],f[N],val[N][3],bh[N],dp[2][V];
int tot,last[N];
struct Edge{int from,to,s;}edges[M<<1];
template<typename T> void read(T &x)
{
    int k=0; char c=getchar();
    x=0;
    while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
    if (c==EOF)exit(0);
    while(isdigit(c))x=x*10+c-'0',c=getchar();
    x=k?-x:x;
}
void AddEdge(int x,int y)
{
    edges[++tot]=Edge{x,y,last[x]};
    last[x]=tot;
}
void dfs(int x,int id)
{
    f[x]=1;
    bh[x]=id;
    for(int i=last[x];i;i=edges[i].s)
    {
        Edge &e=edges[i];
        if (!f[e.to])dfs(e.to,-id);
    }
}
void work()
{
    memset(f,0,sizeof(f));
    memset(val,0,sizeof(val));
    memset(dp,0,sizeof(dp));
    memset(last,0,sizeof(last));//
    tot=0;
    int sum=0,num=0;
    read(n); read(m);
    for(int i=1;i<=n;i++)read(a[i]),a[i]/=100,sum+=a[i];
    for(int i=1;i<=m;i++)
    {
        int x,y;
        read(x); read(y);
        AddEdge(x,y);
        AddEdge(y,x);
    }
    for(int i=1;i<=n;i++)if (!f[i])dfs(i,++num);
    for(int i=1;i<=n;i++)val[abs(bh[i])][bh[i]/abs(bh[i])+1]+=a[i];
    int selfsum=sum/2,k=0;
    dp[k][0]=1;
    for(int i=1;i<=num;i++)
    {
        k^=1;
        for(int j=selfsum;j>=0;j--)
        {
            if (j-val[i][0]>=0&&dp[1-k][j-val[i][0]]>0) dp[k][j]=1;
            else
            if (j-val[i][2]>=0&&dp[1-k][j-val[i][2]]>0) dp[k][j]=1;
            else dp[k][j]=0;
            if (i==num&&dp[k][j]>0){printf("%d
",max(j,(sum-j))*100);return;}
        }
    }
        
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("aa.in","r",stdin);
#endif
    int q;read(q); while(q--)work();}
原文地址:https://www.cnblogs.com/mmmqqdd/p/10986069.html