D. Miku and Generals

ゝ一世哀愁。 2023-07-03 12:26 87阅读 0赞

题目链接:https://nanti.jisuanke.com/t/39271
本题是要你进行选取,使得两个部分的差值最小,然后输入最大的那个值。
通过x+y=sum x-y=mul。我们可以知道,只要我们求出差值,就可以的到题目所要值。
故本题转换为通过选取得到两个部分,使得差值最小,求最小差值。
本题唯一限制点在于部分数据是对立的。
我们可以把所有对立的数据通过01染色得到染色为0和染色为1的点的差值。
同时,如果没有对立点的情况下,那差值就是他本身。这样,我们就可以得到,选取每个部分,对整体所产生的差值影响了。
每个部分所产生差值影响,我们得到了。 那么,我们就可以使用可行性背包,得到最小差值。同时,注意到差值可能为负,所以,我们运用小技巧,把dp[0][MX]当成差值为0的地方。这样负值也可以表示出来了。

  1. #include"string.h"
  2. #include"vector"
  3. #include"algorithm"
  4. using namespace std;
  5. const int N = 300;
  6. const int MX = 1.5e5 + 5;
  7. const int maxn = 3e5 + 5;
  8. int T,n,m;
  9. int a[N],b[N];
  10. vector<int> G[N];
  11. int vis[N],sum1,sum2;
  12. int dp[205][maxn];
  13. int num;
  14. void dfs(int x,int flag)
  15. {
  16. vis[x] = 1;
  17. if(flag == 0) sum1 += a[x];
  18. else sum2 += a[x];
  19. for(int i = 0; i < G[x].size(); i ++)
  20. {
  21. if(vis[G[x][i]] == 0)
  22. {
  23. dfs(G[x][i],!flag);
  24. }
  25. }
  26. }
  27. int main()
  28. {
  29. scanf("%d",&T);
  30. while(T --)
  31. {
  32. scanf("%d%d",&n,&m);
  33. num = 0;
  34. for(int i = 1; i <= n; i ++)
  35. {
  36. vis[i] = 0; G[i].clear();
  37. scanf("%d",&a[i]);
  38. a[i] /= 100; num += a[i];
  39. }
  40. for(int i = 1; i <= m; i ++)
  41. {
  42. int u,v; scanf("%d%d",&u,&v);
  43. G[u].push_back(v);
  44. G[v].push_back(u);
  45. }
  46. int ret = 0;
  47. int top = 0;
  48. for(int i = 1; i <= n; i ++)
  49. {
  50. if(vis[i] == 0)
  51. {
  52. sum1 = sum2 = 0;
  53. dfs(i,0);
  54. int mul = abs(sum1 - sum2);
  55. ret += mul;
  56. if(mul != 0)
  57. b[++ top] = mul;
  58. }
  59. }
  60. memset(dp,0,sizeof(dp));
  61. dp[0][MX] = 1;
  62. for(int i = 1; i <= top; i ++)
  63. {
  64. for(int j = -ret; j <= ret; j ++)
  65. {
  66. if(dp[i - 1][j - b[i] + MX]) dp[i][j + MX] = 1;
  67. if(dp[i - 1][j + b[i] + MX]) dp[i][j + MX] = 1;
  68. }
  69. }
  70. int loc = 0;
  71. for(int i = MX; i <= MX + ret; i ++)
  72. if(dp[top][i]) {
  73. loc = i - MX; break;
  74. }
  75. printf("%d\n",100 * ((num + loc) / 2));
  76. }
  77. }

发表评论

表情:
评论列表 (有 0 条评论,87人围观)

还没有评论,来说两句吧...

相关阅读