uva1627(模型转换01背包)

题意:有n(n<=100)个人,把他们分成非空的两组,使得每个人都被分到一组,且同组中的人相互认识。要求两组的成员人数尽量接近。多解时输出任意方案,无解时输出No Solution。

解法:如果两人不是相互都认识,就连一条无向边。所以就变成了一个无向图。对于每一个连通分量来说,必须是个二分染色图,否则就No solution。然后对于每个联通分量,黑白两种颜色有个数量差,用所有的差来进行01背包,找到距离集合差0最小的方案。

代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=110;
const LL INF=0x3FFFFFFF;
int n;
int rem[Max][Max];
vector<int> dp;
vector<int> vec[Max];
int vis[Max];
int fin[Max];
int sad[Max];
int dfs(int t,int y,int cas)
{
    vis[t]=cas;
    if(fin[t]==y)
        return 0;
    if(fin[t]!=-1)
        return -1;
    fin[t]=y;
    sad[t]=y;
    for(int i=0; i<vec[t].size(); i++)
        if(dfs(vec[t][i],y^1,cas)==-1)
            return -1;
    return 0;
}
int ans[Max][Max*3];
int out[Max][Max*3];
int be[Max][Max*3];
int main()
{
    //freopen ("in.txt" , "r" , stdin);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1; i<=n; i++)
            vec[i].clear();
        memset(vis,-1,sizeof vis);
        dp.clear();
        memset(rem,0,sizeof rem);
        for(int i=1; i<=n; i++)
        {
            int c;
            while(scanf("%d",&c)==1&&c)
            {
                rem[i][c]=1;
            }
            rem[i][i]=1;
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
                if((!rem[i][j])||(!rem[j][i]))
                    vec[i].push_back(j);
        }
        bool flag=0;
        int cas=0;
        memset(sad,0,sizeof sad);
        for(int i=1; i<=n; i++)
        {
            memset(fin,-1,sizeof fin);
            if(vis[i]!=-1)
                continue;
            if(dfs(i,0,cas++)==-1)
            {
                flag=1;
                break;
            }
            int t1=0, t2=0;
            for(int i=1; i<=n; i++)
                if(fin[i]==0)
                    t1++;
                else if(fin[i]==1)
                    t2++;
            dp.push_back(t1-t2);
        }
        if(flag)
        {
            puts("No solution");
             if(t>0)
        cout<<endl;
            continue;
        }
        memset(ans,0,sizeof ans);
        memset(be,0,sizeof be);
        ans[0][100+dp[0]]=1;
        out[0][100+dp[0]]=0;
        ans[0][100-dp[0]]=1;
        out[0][100-dp[0]]=1;
        for(int i=1; i<dp.size(); i++)
        {
            for(int j=0; j<=100*2; j++)
            {
                if(ans[i-1][j])
                {
                    ans[i][j+dp[i]]=1;
                    out[i][j+dp[i]]=0;
                    be[i][j+dp[i]]=j;
                    ans[i][j-dp[i]]=1;
                    out[i][j-dp[i]]=1;
                    be[i][j-dp[i]]=j;
                }
            }
        }
        int m=dp.size();
        vector<int> ans0;
        vector<int> ans1;
        for(int i=0; i<=100; i++)
        {
            if(ans[m-1][100-i]==1||ans[m-1][100+i]==1)
            {
                int num;
                if(ans[m-1][100-i]==1)
                    num=100-i;
                else
                    num=100+i;
                for(int k=m-1; k>=0; k--)
                {
                    for(int i=1; i<=n; i++)
                    {
                        if(vis[i]==k&&sad[i]==out[k][num])
                            ans0.push_back(i);
                        if(vis[i]==k&&sad[i]==1-out[k][num])
                            ans1.push_back(i);
                    }
                    num=be[k][num];
                }
                break;
            }
        }
        cout<<ans0.size();
        for(int i=0; i<ans0.size(); i++)
            cout<<" "<<ans0[i];
        cout<<endl;
        cout<<ans1.size();
        for(int i=0; i<ans1.size(); i++)
            cout<<" "<<ans1[i];
        cout<<endl;
        if(t>0)
        cout<<endl;
    }
    return 0;
}
时间: 2024-11-08 19:43:04

uva1627(模型转换01背包)的相关文章

动态规划——背包问题python实现(01背包、完全背包、多重背包)

目录 01背包问题 完全背包问题 多重背包问题 参考: 背包九讲--哔哩哔哩 背包九讲 01背包问题 01背包问题 描述: 有N件物品和一个容量为V的背包. 第i件物品的体积是vi,价值是wi. 求解将哪些物品装入背包,可使这些物品的总体积不超过背包流量,且总价值最大. 二维动态规划 f[i][j] 表示只看前i个物品,总体积是j的情况下,总价值最大是多少. result = max(f[n][0~V]) f[i][j]: 不选第i个物品:f[i][j] = f[i-1][j]; 选第i个物品:

多重背包转换成完全背包和01背包

void CompletePack(int cost,int weight)   多重背包 { for(int i=cost;i<=m;i++) dp[i]=max(dp[i],dp[i-cost]+weight); } void ZeroOnePack(int cost,int weight)    01背包 { for(int i=m;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]+weight); } void MultiplyPack(int cost,

hdu 1864 最大报销额 模型为简单的01背包

很简单的01背包,但是题目还是很蛋疼的注意题目中600,和1000这两个数,还有就是double和int的转换,1A了感觉还是不错的 /************************************************************************* > File Name: hdu1864.cpp > Author: yang > Mail:[email protected] > Created Time: 2014年08月23日 星期六 14:0

动态规划--01背包模型

01背包剖析 问题引入 题目来源:ACwing:01背包问题 有 N 件物品和一个容量是 V 的背包.每件物品只能使用一次.第 i 件物品的体积是 vi,价值是 wi.求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大.输出最大价值. 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积. 接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值. 输出格式 输出一个整数,表示最大价值. 数据范围 0<N,V≤1000

有关货币问题的动态规划题目--有关01背包,完全背包,多重背包

背包dp:参考背包九讲以及给出一些题目 01背包 (先枚举物品,再逆序枚举容量) 给定n件物品和一个容量为V的背包,每件物品的体积是w[i],价值是va[i](1<=i<=n),求在不超过背包的容量的情况下,怎么选择装这些物品使得得到的价值最大? 例如:有5件物品,体积分别是{2,2,6,5,4},价值分别是{6,3,5,4,6} 递归式:F(i,v)=max(F(i-1,v), F(i-1,v-w[i])+va[i]),其中F(i,v)表示把前i种物品恰放入背包容量为v时取得的最大价值 把这

01背包//简直要被这道题玩死(掀桌)

先上链接: 表格什么的最清楚了:http://blog.csdn.net/mu399/article/details/7722810 dd大大的背包九讲: —————————————————— 01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] } f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值. Pi表示第i件物品的价值. 决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中

背包之01背包、完全背包、多重背包详解

首先说下动态规划,动态规划这东西就和递归一样,只能找局部关系,若想全部列出来,是很难的,比如汉诺塔.你可以说先把除最后一层的其他所有层都移动到2,再把最后一层移动到3,最后再把其余的从2移动到3,这是一个直观的关系,但是想列举出来是很难的,也许当层数n=3时还可以模拟下,再大一些就不可能了,所以,诸如递归,动态规划之类的,不能细想,只能找局部关系. 1.汉诺塔图片 (引至杭电课件:DP最关键的就是状态,在DP时用到的数组时,也就是存储的每个状态的最优值,也就是记忆化搜索) 要了解背包,首先得清楚

hdu 2955 Robberies(01背包)

Robberies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17723    Accepted Submission(s): 6544 Problem Description The aspiring Roy the Robber has seen a lot of American movies, and knows that

hdu 1561The more, The Better(树形dp&amp;01背包)

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4949    Accepted Submission(s): 2918 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝