zoukankan      html  css  js  c++  java
  • 2019 ACM/ICPC Asia Regional shanxia D Miku and Generals (二分图黑白染色+01背包)

    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 100100 ), 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 00 . 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)T(1T10) 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)N(2N200) and thenumber of pairs of generals that have contradictions⁡ M(0 le M le 200)M(0M200).

    The second line contains NN integers, and the ii-th integer is c_ici, which is the attack power value of the ii-th general (0 le c_i le 5 imes 10^4)(0ci5×104).

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

    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 22 and 33 .

    样例输入

    1
    4 2
    1400 700 2100 900 
    1 3
    3 4

    样例输出

    2800


    题意:给你n个数,让你分成两堆,堆与堆之间的和的差值最小,中间值与值之间可能存在矛盾,不能分在同一组,问你分配后最大的那一组的值是多少
    思路:首先我们知道很多矛盾对,但是有可能一个人与多个人都有矛盾,所以为了避免分组的时候发生矛盾,我们很容易就想到二分图的黑白染色,这样我们首先就可以
    解决矛盾问题,然后我们要每个联通块,我们首先可以求所有的和2x,那么x肯定是最优情况,我们又再每个连通块里面选最小的值,和就是y,(一个数为连通块时,另一个就是0,设计巧妙的地方),
    然后我们要使y更接近x,所以我们就求x-y的容量,在每个连通块的差值里面选多少交换来求最大,然后这里就相当于转换为一个01背包问题
    #include<bits/stdc++.h>
    #define maxn 100005
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    ll n,m;
    ll a[maxn],b[maxn];
    vector<int> mp[maxn];
    ll s,dp[maxn];
    int vis[maxn];
    void dfs(int x,int num){
        vis[x]=s+num;
        for(int i=0;i<mp[x].size();i++){
            if(vis[mp[x][i]]==0){
                if(num==0){
                    dfs(mp[x][i],1);
                }
                else{
                    dfs(mp[x][i],0);
                }
            }
        } 
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            for(int i=0;i<maxn;i++) mp[i].clear();
            scanf("%lld%lld",&n,&m);
            for(int i=1;i<=n;i++){
                scanf("%lld",&a[i]);
                a[i]/=100;
            }
            int x,y;
            for(int i=0;i<m;i++){
                scanf("%d%d",&x,&y);
                mp[x].push_back(y);
                mp[y].push_back(x); 
            }
            s=1;
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;i++){
                if(vis[i]==0){
                    dfs(i,0);
                    s+=2;
                }
            }
            s--;
            ll sum=0,num=0;
            memset(b,0,sizeof(b)); 
            for(int i=1;i<=n;i++){
                b[vis[i]]+=a[i];
                sum+=a[i];
            }
            int q=1;
    
            for(int i=1;i<=s;i+=2){
                num+=min(b[i],b[i+1]);
                b[q++]=abs(b[i]-b[i+1]);
            }
            ll z=sum/2+sum%2;
            z-=num;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<q;i++){
                for(int j=z;j>=b[i];j--){
                    dp[j]=max(dp[j],dp[j-b[i]]+b[i]);
                }
            }
            ll z1=num;
            if(dp[z] != -1) z1+=dp[z];
            ll z2=sum-z1;
            printf("%lld
    ",max(z1,z2)*100);
        }
    }
    /*
    1
    4 2
    1400 700 2100 900 
    1 3
    3 4
    */



  • 相关阅读:
    xml
    反射
    类加载器
    tcp通信
    UDP通信
    UDP与TCP协议
    网络通信协议
    符合汽车安全和质量标准的CYPRESS FRAM
    SRAM是什么存储器
    网络通信与便携式应用驱动SRAM技术发展
  • 原文地址:https://www.cnblogs.com/Lis-/p/10952021.html
Copyright © 2011-2022 走看看