记录编号 |
442172 |
评测结果 |
AAAAAAAAAAA |
题目名称 |
子集 |
最终得分 |
100 |
用户昵称 |
FoolMike |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.031 s |
提交时间 |
2017-08-26 12:21:37 |
内存使用 |
4.87 MiB |
显示代码纯文本
- #include<cstdio>
- #include<algorithm>
- using namespace std;
- const int N=1e5+10;
- int n,m,id,v[N],w[N],head[N],next[N];
- bool incir[N];
- void add(int f,int t){
- static int cnt=1;
- w[++cnt]=t;
- next[cnt]=head[f];
- head[f]=cnt;
- }
- int fa[N],up[N];
- bool vis[N],use[N],cir[N];
- void dfs(int x){
- vis[x]=1;
- for (int i=head[x];i;i=next[i])
- if (!use[i]){
- use[i]=use[i^1]=1;
- int v=w[i];
- if (v==fa[x]) continue;
- if (vis[v]){
- id++;
- add(id,v);add(v,id);
- cir[i]=cir[i^1]=1;
- for (int i=x;i!=v;i=fa[i]){//按顺序加边,以便后面dp使用
- add(id,i);add(i,id);
- cir[up[i]]=cir[up[i]^1]=1;
- }
- }
- else up[v]=i,fa[v]=x,dfs(v);
- }
- }
- int dp[N][2];//dp[i][j]表示以i为根的仙人掌中取/不取根的最大独立集
- void solve(int x,int fa){
- if (x<=n){//圆点
- dp[x][1]=v[x];
- for (int i=head[x];i;i=next[i])
- if (!cir[i]&&w[i]!=fa){
- int v=w[i];
- solve(v,x);
- if (v<=n) dp[x][1]+=dp[v][0],dp[x][0]+=max(dp[v][0],dp[v][1]);
- else dp[x][1]+=dp[v][1],dp[x][0]+=dp[v][0];
- }
- }
- else{//方点
- for (int i=head[x];i;i=next[i])
- if (!cir[i]&&w[i]!=fa) solve(w[i],x);
- //从根开始,化环为链
- static int q[N],f[N][2];//f[i][j]表示前i个中选/不选最后一个的最大独立集
- int size=0;
- for (int i=head[x];i;i=next[i])
- if (!cir[i]&&w[i]!=fa) q[++size]=w[i];
- //求dp[x][1]
- f[1][0]=dp[q[1]][0];f[1][1]=-1e9;
- for (int i=2;i<=size;i++)
- 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];
- dp[x][1]=f[size][0];
- //求dp[x][0]
- f[1][0]=dp[q[1]][0];f[1][1]=dp[q[1]][1];
- for (int i=2;i<=size;i++)
- 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];
- dp[x][0]=max(f[size][0],f[size][1]);
- }
- }
- int main()
- {
- freopen("subseta.in","r",stdin);
- freopen("subseta.out","w",stdout);
- scanf("%d",&n);id=n;
- for (int i=1;i<=n;i++) scanf("%d",&v[i]);
- scanf("%d",&m);
- for (int i=1;i<=m;i++){
- int u,v;
- scanf("%d%d",&u,&v);
- add(u,v);add(v,u);
- }
- int ans=0;
- for (int i=1;i<=n;i++)
- if (!vis[i]) dfs(i),solve(i,0),ans+=max(dp[i][0],dp[i][1]);
- printf("%d\n",ans);
- return 0;
- }