zoukankan      html  css  js  c++  java
  • hdu 5312 dp(背包)、二分图或其他姿势

    题意:给出一个二分图(不一定连通),问最多能加多少边,使它仍然是二分图

    BC周年庆第四题,貌似终判再终判之后数据还是有问题```

    据说貌似可以用bitset搞,而且姿势优美是正解```然而我还是用的dp过的

    首先就是用黑白染色判断每个区块的两边点的个数,接着因为要边数最多,所以显然要两边点数尽量接近,所以我就用01背包的方法,计算能够得到的 n/2 内的半边最大点数,中间加入已达到的最大值优化和黑白染色得到单点额外记录而不进入背包的优化```然后从TLE变成了200+ms过,只能说出数据的太执着于单点,如果构造出一张全是两点连线的图,大概妥妥爆炸```这个测试样例好鱼```然后就这样“卡”过去了,大概bitset才是真-正解吧```

      1 #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<algorithm>
      5 #include<math.h>
      6 using namespace std;
      7 
      8 int head[10005],nxt[200005],point[200005],size=0;
      9 int num[2];
     10 int c[10005],dp[10005];
     11 
     12 int max(int a,int b){
     13     return a>b?a:b;
     14 }
     15 
     16 int min(int a,int b){
     17     return a<b?a:b;
     18 }
     19 
     20 int read(){
     21     int x=0;
     22     char c=getchar();
     23     while(c>'9'||c<'0')c=getchar();
     24     while(c>='0'&&c<='9'){
     25         x=x*10+c-'0';
     26         c=getchar();
     27     }
     28     return x;
     29 }
     30 
     31 void add(int a,int b){
     32     point[size]=b;
     33     nxt[size]=head[a];
     34     head[a]=size++;
     35     point[size]=a;
     36     nxt[size]=head[b];
     37     head[b]=size++;
     38 }
     39 
     40 void dfs(int a,int x){
     41     c[a]=x;
     42     num[x]++;
     43     for(int i=head[a];~i;i=nxt[i]){
     44         int b=point[i];
     45         if(c[b]==-1)dfs(b,!x);
     46     }
     47 }
     48 
     49 int main(){
     50     int T=read();
     51     while(T--){
     52         int n=read();
     53         int m=read();
     54         memset(head,-1,sizeof(head));
     55         size=0;
     56         memset(c,-1,sizeof(c));
     57         int i,j;
     58         if(m==0){
     59             int a=n/2;
     60             printf("%d
    ",a*(n-a));
     61             continue;
     62         }
     63         for(i=1;i<=m;i++){
     64             int a=read();
     65             int b=read();
     66             add(a,b);
     67         }
     68         int cnt=0,ans=0,maxx=0;
     69         memset(dp,-1,sizeof(dp));
     70         dp[0]=0;
     71         int k=0;
     72         for(i=1;i<=n;++i){
     73             if(c[i]==-1){
     74                 num[0]=num[1]=0;
     75                 dfs(i,1);
     76                 if(num[0]+num[1]==1){
     77                     k++;
     78                     continue;
     79                 }
     80                 for(j=min(n/2,maxx+max(num[0],num[1]));j>=0;--j){
     81                     if(j-num[0]>=0&&dp[j-num[0]]==cnt){
     82                         dp[j]=cnt+1;
     83                         maxx=max(maxx,j);
     84                         ans=max(ans,j);
     85                     }
     86                     if(j-num[1]>=0&&dp[j-num[1]]==cnt){
     87                         dp[j]=cnt+1;
     88                         maxx=max(maxx,j);
     89                         ans=max(ans,j);
     90                     }
     91                 }
     92                 cnt++;
     93             }
     94         }
     95         ans=min(ans+k,n/2);
     96         int x1=n-ans;
     97         printf("%d
    ",x1*ans-m);
     98     }
     99     return 0;
    100 }
    View Code
  • 相关阅读:
    记一道乘法&加法线段树(模版题)
    2021CCPC网络赛(重赛)题解
    Codeforces Round #747 (Div. 2)题解
    F. Mattress Run 题解
    Codeforces Round #744 (Div. 3) G题题解
    AtCoder Beginner Contest 220部分题(G,H)题解
    Educational Codeforces Round 114 (Rated for Div. 2)题解
    Codeforces Global Round 16题解
    Educational Codeforces Round 113 (Rated for Div. 2)题解
    AtCoder Beginner Contest 182 F
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4676928.html
Copyright © 2011-2022 走看看