记录编号 442172 评测结果 AAAAAAAAAAA
题目名称 子集 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.031 s
提交时间 2017-08-26 12:21:37 内存使用 4.87 MiB
显示代码纯文本
  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int N=1e5+10;
  5. int n,m,id,v[N],w[N],head[N],next[N];
  6. bool incir[N];
  7. void add(int f,int t){
  8. static int cnt=1;
  9. w[++cnt]=t;
  10. next[cnt]=head[f];
  11. head[f]=cnt;
  12. }
  13. int fa[N],up[N];
  14. bool vis[N],use[N],cir[N];
  15. void dfs(int x){
  16. vis[x]=1;
  17. for (int i=head[x];i;i=next[i])
  18. if (!use[i]){
  19. use[i]=use[i^1]=1;
  20. int v=w[i];
  21. if (v==fa[x]) continue;
  22. if (vis[v]){
  23. id++;
  24. add(id,v);add(v,id);
  25. cir[i]=cir[i^1]=1;
  26. for (int i=x;i!=v;i=fa[i]){//按顺序加边,以便后面dp使用
  27. add(id,i);add(i,id);
  28. cir[up[i]]=cir[up[i]^1]=1;
  29. }
  30. }
  31. else up[v]=i,fa[v]=x,dfs(v);
  32. }
  33. }
  34. int dp[N][2];//dp[i][j]表示以i为根的仙人掌中取/不取根的最大独立集
  35. void solve(int x,int fa){
  36. if (x<=n){//圆点
  37. dp[x][1]=v[x];
  38. for (int i=head[x];i;i=next[i])
  39. if (!cir[i]&&w[i]!=fa){
  40. int v=w[i];
  41. solve(v,x);
  42. if (v<=n) dp[x][1]+=dp[v][0],dp[x][0]+=max(dp[v][0],dp[v][1]);
  43. else dp[x][1]+=dp[v][1],dp[x][0]+=dp[v][0];
  44. }
  45. }
  46. else{//方点
  47. for (int i=head[x];i;i=next[i])
  48. if (!cir[i]&&w[i]!=fa) solve(w[i],x);
  49. //从根开始,化环为链
  50. static int q[N],f[N][2];//f[i][j]表示前i个中选/不选最后一个的最大独立集
  51. int size=0;
  52. for (int i=head[x];i;i=next[i])
  53. if (!cir[i]&&w[i]!=fa) q[++size]=w[i];
  54. //求dp[x][1]
  55. f[1][0]=dp[q[1]][0];f[1][1]=-1e9;
  56. for (int i=2;i<=size;i++)
  57. f[i][1]=f[i-1][0]+dp[q[i]][1],f[i][0]=max(f[i-1][0],f[i-1][1])+dp[q[i]][0];
  58. dp[x][1]=f[size][0];
  59. //求dp[x][0]
  60. f[1][0]=dp[q[1]][0];f[1][1]=dp[q[1]][1];
  61. for (int i=2;i<=size;i++)
  62. f[i][1]=f[i-1][0]+dp[q[i]][1],f[i][0]=max(f[i-1][0],f[i-1][1])+dp[q[i]][0];
  63. dp[x][0]=max(f[size][0],f[size][1]);
  64. }
  65. }
  66. int main()
  67. {
  68. freopen("subseta.in","r",stdin);
  69. freopen("subseta.out","w",stdout);
  70. scanf("%d",&n);id=n;
  71. for (int i=1;i<=n;i++) scanf("%d",&v[i]);
  72. scanf("%d",&m);
  73. for (int i=1;i<=m;i++){
  74. int u,v;
  75. scanf("%d%d",&u,&v);
  76. add(u,v);add(v,u);
  77. }
  78. int ans=0;
  79. for (int i=1;i<=n;i++)
  80. if (!vis[i]) dfs(i),solve(i,0),ans+=max(dp[i][0],dp[i][1]);
  81. printf("%d\n",ans);
  82. return 0;
  83. }