zoukankan      html  css  js  c++  java
  • poj 1112

    二着色+DP

    在不是互相认识的节点之间连一条边,最后得到由多个连通分量构成的图。把图中节点分为两组,保证图中每条边的两个顶点不能再同一组。对每个连通分量进行二着色,每个连通分量的点就分为了a,b两组。假定最后整个图分为1,2两组。每个连通分量的a,b两组,无非一个在1组一个在2组,通过DP,确定每个连通分量中a,b哪个在1组,哪个在2组时最有。然后就是DP的过程,没想出来,看了其他人的结题报告。f[i][j]表示对于前i个联通分量,是否可达到第1组和第2组的差值为j的状态。设a为连通分量i的两组的差值则f[i][j]=1当f[i-1][j-a]==1||f[i-1][j+a]==1。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 using namespace std;
      5 const int maxn=100+10;
      6 int g[maxn][maxn];
      7 int color[maxn];
      8 int mark[maxn][3][maxn];
      9 int amount[maxn][maxn*2];
     10 int co1[maxn][3];
     11 int n,tot;
     12 int f[maxn][maxn*2],path[maxn][maxn*2];
     13 int dfs_color(int u)
     14 {
     15     int i;
     16     for(i=1;i<=n;i++)
     17     {
     18         if(i!=u&&(!g[u][i]||!g[i][u]))
     19         {
     20             if(color[i]==color[u]) return 0;
     21             if(!color[i])
     22             {
     23                 color[i]=3-color[u];
     24                 mark[tot][color[i]][co1[tot][color[i]]++]=i;
     25                 if(!dfs_color(i)) return 0;
     26             }
     27         }
     28     }
     29     return 1;
     30 }
     31 void print(int ans)
     32 {
     33     printf("%d",amount[tot][ans]);
     34     int i,j,loc,tem=ans;
     35     for(i=tot;i>=1;i--)
     36     {
     37         loc=path[i][tem];
     38         for(j=0;j<co1[i][loc];j++) printf(" %d",mark[i][loc][j]);
     39         tem=tem-(co1[i][loc]-co1[i][3-loc]);
     40     }
     41     tem=ans;
     42     printf("
    ");
     43     printf("%d",n-amount[tot][ans]);
     44     for(i=tot;i>=1;i--)
     45     {
     46         loc=3-path[i][tem];
     47         for(j=0;j<co1[i][loc];j++) printf(" %d",mark[i][loc][j]);
     48         tem=tem-(co1[i][3-loc]-co1[i][loc]);
     49     }
     50     printf("
    ");
     51 }
     52 int main()
     53 {
     54     scanf("%d",&n);
     55     int i,tem,j,a;
     56     for(i=1;i<=n;i++)
     57     {
     58         while(scanf("%d",&tem)&&tem) g[i][tem]=1;
     59     }
     60     int flag=0;
     61     tot=0;
     62     for(i=1;i<=n;i++)
     63     {
     64         if(!color[i])
     65         {
     66             tot++;
     67             color[i]=1;
     68             mark[tot][1][co1[tot][1]++]=i;
     69             if(!dfs_color(i))
     70             {
     71                 flag=1;
     72                 break;
     73             }
     74         }
     75     }
     76     if(flag) printf("No solution
    ");
     77     else
     78     {
     79         int a1,a2;
     80         f[1][co1[1][1]-co1[1][2]+n]=1;
     81         f[1][co1[1][2]-co1[1][1]+n]=1;
     82         path[1][co1[1][1]-co1[1][2]+n]=1;
     83         path[1][co1[1][2]-co1[1][1]+n]=2;
     84         amount[1][co1[1][1]-co1[1][2]+n]=co1[1][1];
     85         amount[1][co1[1][2]-co1[1][1]+n]=co1[1][2];
     86         for(i=2;i<=tot;i++)
     87         {
     88             a=co1[i][1]-co1[i][2];
     89             for(j=0;j<=2*n;j++)
     90             {
     91                 if((j-a)>=0&&(j-a)<=2*n&&f[i-1][j-a]==1)
     92                 {
     93                     f[i][j]=1;
     94                     path[i][j]=1;
     95                     amount[i][j]=amount[i-1][j-a]+co1[i][1];
     96                 }
     97                 else if((j+a)>=0&&(j+a)<=2*n&&f[i-1][j+a]==1)
     98                 {
     99                     f[i][j]=1;
    100                     path[i][j]=2;
    101                     amount[i][j]=amount[i-1][j+a]+co1[i][2];
    102                 }
    103             }
    104         }
    105 
    106         for(i=n;i<=2*n;i++) if(f[tot][i]) break;
    107         for(j=n-1;j>=0;j--) if(f[tot][j]) break;
    108         int ans=(i-n)<(n-j)?i:j;
    109         print(ans);
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    开源项目SMSS发开指南(四)——SSL/TLS加密通信详解(上)
    开源项目SMSS发开指南(三)——protobuf协议设计
    开源项目SMSS开发指南(二)——基于libevent的线程池
    开源项目SMSS开发指南
    萧瑟斩落叶,孤月伴影长
    TCP/IP和Socket开发经验分享
    Linux C++轻量级开发指南
    如何使用threejs实现第一人称视角的移动
    图形辅助,理解递归
    字节的游戏
  • 原文地址:https://www.cnblogs.com/lj030/p/3161251.html
Copyright © 2011-2022 走看看