2019 西安邀请赛 D
Posted tingtin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 西安邀请赛 D相关的知识,希望对你有一定的参考价值。
1 //n件物品,m种关系,(有关系的2个不能在同一组) 2 //把所有物品分为2组,希望最后2组的差值尽可能小,输出较大者 3 /* 4 二分图涂色+可行性(01)背包 5 dp[i] =1表示 最后差值为i可行 6 建图后,对于每个连通分量记录差值,来求所有的可行 7 */ 8 #include<bits/stdc++.h> 9 using namespace std; 10 int t,n,m; 11 #define N 250 12 #define M 102000 13 int a[N],head[N],sum; 14 int cnt,vis[N]; 15 int dp[M],dp1[M]; 16 int sum1=0,sum2=0; 17 void init() 18 cnt = 0; 19 for(int i =0;i<N;i++) 20 head[i] = -1; 21 vis[i] =0;//多组输入 22 23 24 struct Node 25 int u,v,nex; 26 e[N*2]; 27 void add(int u,int v) 28 29 e[cnt].u=u;e[cnt].v=v; 30 e[cnt].nex=head[u];head[u]=cnt++; 31 32 void dfs(int x,int rt) 33 vis[x] = 1; 34 if(rt==0) 35 sum1+=a[x]; 36 else 37 sum2+=a[x]; 38 39 for(int i =head[x];i!=-1;i=e[i].nex) 40 int v = e[i].v; 41 if(!vis[v]) 42 dfs(v,rt^1);//0^1=1,1^1=0 43 44 45 int main() 46 47 scanf("%d",&t); 48 while(t--) 49 50 init(); 51 scanf("%d%d",&n,&m); 52 int x,y; 53 sum =0; 54 for(int i =1;i<=n;i++) 55 56 scanf("%d",&a[i]); 57 sum+=a[i]/100; 58 a[i]/=100;//题目说明都是100的倍数 59 60 for(int i =0;i<m;i++) 61 scanf("%d%d",&x,&y); 62 add(x,y);add(y,x);//无向图 63 64 65 int num; 66 for(int i =0;i<=sum;i++) dp[i] = 0; 67 dp[0] = 1;//dp[0]一定先设为1,来引入第一个差值 68 for(int i =1;i<=n;i++) 69 if(!vis[i]) 70 sum1=0,sum2=0; 71 dfs(i,0); 72 num = abs(sum1-sum2); 73 //printf("%d %d %d\n",sum1,sum2,num); 74 for(int j=sum;j>=0;j--) 75 if(dp[j]) 76 //如 :0,j. 0 ,num 或者 j,0.0,num 77 if(abs(j+num)<=sum) dp1[abs(j+num)] =1; 78 dp1[abs(j-num)] =1; 79 80 81 for(int j =sum;j>=0;j--) 82 dp[j] = dp1[j],dp1[j] = 0; 83 84 85 86 //一定需要2个dp 数组,利用dp1一直更新到所有的物品都取完 87 for(int i =0;i<=sum;i++) 88 if(dp[i]) 89 90 printf("%d\n",(sum+i)/2*100); 91 break; 92 93 94 95 return 0; 96
以上是关于2019 西安邀请赛 D的主要内容,如果未能解决你的问题,请参考以下文章
2019 ACM - ICPC 全国邀请赛(西安)题解(9 / 13)