zoukankan      html  css  js  c++  java
  • Miku and Generals(二分图染色+可行性dp)

    题意:

    给你n个人,每个人有一个权值 a_i ​,(a_i​是可以被100整除的))现在需要你将n个人分成两组,有m个关系,a和b有关系代表a和b不能放在同一个组内,为了两组实力尽量平均,要你求两组权值差值最小时最大的值是哪一个

    思路:

    首先我们知道n个人必须全选分为两组,其次题目保证有解

    因此我们很容易想到如果a->b,b->c,那么a一定和c要分在同一组内

    这样我们就得到了很多个联通块

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    const int MAX=200005,INF = 0x3f3f3f3f;
    struct node
    {
        int v,nxt;
    }e[450];
    int head[220],dp[100000],vis[220],top,a[220],b[220];
    int si;
    void add(int u,int v)
    {
        e[top].v=v;
        e[top].nxt=head[u];
        head[u]=top++;
    }
    void dfs(int x,int op)
    {
        vis[x]=si+op;
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            int v=e[i].v;
            if(vis[v]==0)
            {
                if(op==0) 
                    dfs(v,1);
                else 
                    dfs(v,0);
            }
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            int num=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                a[i]/=100;
                num+=a[i];
            }
            memset(head,-1,sizeof(head));
            top=0;
            for(int i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
                add(v,u);
            }
            memset(vis,0,sizeof(vis));
            si=1;
            for(int i=1;i<=n;i++)
            {
                if(vis[i]==0)
                {
                    dfs(i,0);
                    si+=2;
                }
            }
            si--;
            memset(b,0,sizeof(b));
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                b[vis[i]]+=a[i];
            }
            int p=1;
            for(int i=1;i<= si;i+=2)
            {
                sum+=min(b[i],b[i+1]);
                b[p++]=abs(b[i]-b[i+1]);
            }
            memset(dp,0,sizeof(dp));
            m=num/2+num%2;
            m-=sum;
            dp[0]=0;
            for(int i=1;i<p;i++)
            {
                for(int j=m;j>=b[i];j--)
                {
                    dp[j]=max(dp[j],dp[j-b[i]]+b[i]);
                }
            }
            int x=sum;
            if(dp[m]!= -1)
                 x+=dp[m];
            int y=num-x;
            printf("%d
    ",max(x,y)*100);
        }
        return 0;
    }
  • 相关阅读:
    用ildasm和ilasm对.net下的exe程序进行破解初探
    随笔--各种概念等等
    C#高级编程学习一-----------------第五章泛型
    visual studio相关操作
    webservice开发
    delphi各种错
    android开发文章收藏
    android开发遇到的问题
    android应用开发基础知道
    数据库各种问题
  • 原文地址:https://www.cnblogs.com/2462478392Lee/p/12274382.html
Copyright © 2011-2022 走看看