[ARC99E]Independence——二分图染色+DP

题目大意:

给定一个图,要求你把它分为两个团,求最小的端点都在一个团中的边的个数。

思路:

搞成补图之后二分图染色,去除不合法的情况,然后对于每一个联通块中的黑点的个数看成一个物品,白点的个数看成一个物品,每一个联通块只可以选择一种物品,然后跑背包取尽量中间的体积。
然后就错了,这题不是背包,而是一个略区别于背包的DP,每一个泛化物品必须要选定一个,而不能不选。

/*======================
 * Author : ylsoi
 * Problem : ARC99E
 * Algorithm : DP
 * Time : 2018.6.25
 * ===================*/
#include

#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;

using namespace std;

void File(){
    freopen("ARC99E.in","r",stdin);
    freopen("ARC99E.out","w",stdout);
}

const int maxn=700+10;
const int maxm=maxn*maxn;
const int inf=0x3f3f3f3f;
int n,m,beg[maxn],last[maxm],to[maxm],cnte=1;
int a[maxn],b[maxn],tot;
bool G[maxn][maxn],vis[maxn],c[maxn];
bitsetdp;

void add(int u,int v){
    last[++cnte]=beg[u];
    beg[u]=cnte;
    to[cnte]=v;
}

bool dfs(int u,int fr){
    vis[u]=1;
    c[u]=c[fr]^1;
    if(!c[u])++a[tot];
    else ++b[tot];
    for(int i=beg[u];i;i=last[i]){
        if(vis[to[i]] && c[to[i]]==c[u])return false;
        if(!vis[to[i]] && !dfs(to[i],u))return false;
    }
    return true;
}

int main(){
    File();
    scanf("%d%d",&n,&m);
    REP(i,1,m){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u][v]=G[v][u]=1;
    }
    REP(i,1,n)REP(j,1,n)if(!G[i][j] && i!=j)
        add(i,j);
    REP(i,1,n){
        if(vis[i])continue;
        ++tot;
        if(!dfs(i,0)){          
            printf("-1\n");
            return 0;
        }
    }
    dp[0]=1;
    REP(i,1,tot)dp=(dp<for(int i=n/2;i;--i)if(dp[i]){
        printf("%d\n",i*(i-1)/2+(n-i)*(n-i-1)/2);
        return 0;
    }
    return 0;
}

你可能感兴趣的:(二分图,动态规划,背包)