zoukankan      html  css  js  c++  java
  • BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包

    分析:

    一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环!

    有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断出环的情况...

    缩点之后重新建图就需要见d[i]到i了...

    附上代码:

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    #define N 205
    struct node
    {
    	int to,next;
    }e[N];
    int f[N][505],head[N],cnt,dfn[N],low[N],vis[N],sta[N],top,tims,fa[N],n,m,a[N],b[N],in1[N];
    void add(int x,int y){if(!y)return;e[cnt]=(node){y,head[x]};head[x]=cnt++;}
    void tarjan(int x)
    {
    	dfn[x]=low[x]=++tims;sta[++top]=x;vis[x]=1;
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(vis[to1])low[x]=min(dfn[to1],low[x]);
    		else if(!dfn[to1])tarjan(to1),low[x]=min(low[x],low[to1]);
    	}
    	if(dfn[x]==low[x])
    	{
    		while(sta[top]!=x)
    		{
    			fa[sta[top]]=x;
    			vis[sta[top]]=0;
    			top--;
    		}
    		fa[x]=x;vis[x]=0;top--;
    	}
    }
    vector <int>v[N];
    void dfs(int x)
    {
    	for(int i=0;i<v[x].size();i++)
    	{
    		int to1=v[x][i];
    		dfs(to1);
    		for(int j=m;j;j--)
    		{
    			for(int k=j;~k;k--)
    			{
    				f[x][j]=max(f[to1][k]+f[x][j-k],f[x][j]);
    			}
    		}
    	}
    	for(int i=m;i>=b[x];i--)f[x][i]=f[x][i-b[x]]+a[x];
    	for(int i=0;i<b[x];i++)f[x][i]=0;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);memset(head,-1,sizeof(head));
    	for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(int i=1,x;i<=n;i++)scanf("%d",&x),add(i,x);
    	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=head[i];j!=-1;j=e[j].next)
    		{
    			int to1=e[j].to;
    			if(fa[to1]!=fa[i])v[fa[to1]].push_back(fa[i]),in1[fa[i]]++;
    		}
    	}
    	for(int i=1;i<=n;i++)if(fa[i]==i&&(!in1[i]))v[0].push_back(i);
    	for(int i=1;i<=n;i++)if(fa[i]!=i)a[fa[i]]+=a[i];
    	for(int i=1;i<=n;i++)if(fa[i]!=i)b[fa[i]]+=b[i];
    	dfs(0);printf("%d
    ",f[0][m]);return 0;
    }
    

      

  • 相关阅读:
    C# 遍历Hashtable
    asp.net 处理超链接中文参数编码问题
    electronvue开发问题总结
    vue全局使用样式文件vueclipluginstyleresourcesloader
    win10使用VMware安装macOS11.1镜像系统教程
    LVM从CentOS7默认安装的/home中转移空间到根目录/(转载)
    Nginx引用多配置文件
    ssh_exchange_identification: read: Connection reset by peer
    linux修改时区
    修改键盘Tab键为四个空格
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9241922.html
Copyright © 2011-2022 走看看