• 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
  • 相关阅读:
    PAT (Advanced Level) Practice 1097 Deduplication on a Linked List (25分) (静态链表+测试实例)
    PAT (Advanced Level) Practice 1096 Consecutive Factors (20分)
    POJ
    LightOJ
    LibreOJ
    SGU 223 国王 状压DP
    HDU
    CodeForces
    【模板】 拉格朗日插值
    模板 求二次剩余
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4676928.html
Copyright © 2020-2023  润新知