UVA-1627

来源:互联网 发布:微信怎么发淘宝联盟 编辑:程序博客网 时间:2024/06/10 15:05

(二分图染色+01背包),若两人中至少有其中一人不认识对方则建立一条边。

#include"cstdio"#include"iostream"#include"algorithm"#include"cstring"#include"vector"using namespace std;const int MX = 1e5+7;const int maxn = 505;struct edge{    int v,nxt;    edge(){}    edge(int v ,int nxt):v(v), nxt(nxt){}}e[MX];int n;int cnt,tail,head[maxn],col[maxn],sz[maxn],dp[maxn][maxn];vector <int> d[maxn];bool flag;bool mp[maxn][maxn];void init(){    cnt = 1;    flag = 0;    tail = -1;    memset(col,-1,sizeof(col));    memset(head,-1,sizeof(head));    memset(mp,0,sizeof(mp));    for(int i = 0; i <= 2*n+1; i++) d[i].clear();}void Add(int u, int v){    e[++tail] = edge(v,head[u]);    head[u] = tail;}void dfs(int u, int c){    if(flag) return;    col[u] = c;    d[cnt+c].push_back(u);    for(int i = head[u]; ~i; i = e[i].nxt){        int v = e[i].v;        if(col[v] != -1 && col[v]!=c^1){            flag = 1;            return;        }        if(col[v] == -1)            dfs(v,c^1);    }}void Print(){    int now = 0;    for(int i = 0; i <=n ; i++){        if(dp[cnt][n+i] == 1){            now = n+i;            break;        }        else if(dp[cnt][n-i] == 1){            now = n-i;            break;        }    }    vector <int> q1,q2;    for(int i = cnt; i > 0; i--){        if(dp[i-1][now-sz[i]]){            for(int j = 0; j < d[2*i-1].size(); j++) q1.push_back(d[2*i-1][j]);            for(int j = 0; j < d[2*i].size(); j++)   q2.push_back(d[2*i][j]);            now -= sz[i];         }        else{            for(int j = 0; j < d[2*i-1].size(); j++) q2.push_back(d[2*i-1][j]);            for(int j = 0; j < d[2*i].size(); j++)   q1.push_back(d[2*i][j]);            now += sz[i];        }    }    printf("%d",q1.size());    for(int i = 0; i < q1.size(); i++) printf(" %d",q1[i]);    puts("");    printf("%d",q2.size());    for(int i = 0; i < q2.size(); i++) printf(" %d",q2[i]);    puts("");}void DP(){    cnt /= 2;    for(int i = 1; i <= cnt; i++){        sz[i] = d[2*i-1].size() - d[2*i].size();    }    memset(dp,0,sizeof(dp));    dp[0][n] = 1;    int m = 2*n;    for(int i = 1; i <= cnt; i++){        for(int j = m; j >= 0; j--){            if(dp[i-1][j]){                dp[i][j+sz[i]] = 1;                dp[i][j-sz[i]] = 1;            }        }    }    Print();}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%d",&n);        init();        for(int i = 1; i<= n; i++){            int x;            scanf("%d",&x);            while(x){                mp[i][x] = 1;                scanf("%d",&x);            }        }        for(int i = 1; i<= n; i++){            for(int j = 1; j <= n; j++)            if(i != j){                if(mp[i][j] && mp[j][i]) continue;                Add(i,j);            }        }        for(int i = 1; i <= n; i++){            if(col[i] == -1){                dfs(i,0);                cnt += 2;                if(flag){                    puts("No solution\n");                    break;                }            }        }        if(flag) continue;        DP();        if(T) puts("");    }    return 0;}

原创粉丝点击