zoukankan      html  css  js  c++  java
  • 骑士

    https://loj.ac/problem/10162

    题目描述

      每个骑士都有一个战斗力和一个厌恶的人,他不会和厌恶的人一起出征,求最多能达到的最大战斗力。

    思路

      由于题目中每个点必定会连出一条边,所以对于每个连通块内,必定是一棵基环树,对于基环树,我们很难进行(dp),一个简单的方法是我们先求出那个简单环,随后断开环上的任意一条边,以这条边连接的两个点为根做一次树形(dp),并保证根节点不选即可。

      对于在基环树上找环,我们可以考虑用(dfs)序做,当我们访问到一条边从(dfs)序小的访问到已确定(dfs)序大的节点时,这两个点必定是环上的两点,不断往回跳记录答案即可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+10;
    
    ll read()
    {
    	ll res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    void write(ll x)
    {
    	if(x<0){putchar('-');x=-x;}
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    }
    
    int head[N],tot=1,to[N<<1],nxt[N<<1];
    void add_edge(int x,int y)
    {
    	nxt[++tot]=head[x];
    	head[x]=tot;
    	to[tot]=y;
    }
    int dfn[N],idx,fa[N],loop[N],cnt;
    void get_loop(int u)
    {
    	dfn[u]=++idx;
    	for(int i=head[u];i;i=nxt[i])
    	{
    		int v=to[i];
    		if(v==fa[u])continue ;
    		if(dfn[v])
    		{
    			if(dfn[v]<dfn[u])continue ;
    			loop[++cnt]=v;
    			for(;v!=u;v=fa[v])
    				loop[++cnt]=fa[v];
    		}
    		else
    		{
    			fa[v]=u;
    			get_loop(v);
    		}
    	}
    }
    ll a[N],f[N][2],st;
    void dfs(int u,int fa)
    {
    //	cout<<u<<':'<<endl;
    	f[u][1]=a[u];
    	for(int i=head[u];i;i=nxt[i])
    	{
    		int v=to[i];
    		if(v==fa||i==(st^1)||i==st)continue ;
    //		cout<<i<<' '<<v<<endl;
    		dfs(v,u);
    		f[u][0]+=max(f[v][0],f[v][1]);
    		f[u][1]+=f[v][0];
    	}
    }
    
    int main()
    {
    	int n=read();
    	for(int i=1;i<=n;i++)
    	{
    		a[i]=read();
    		int x=read();
    		add_edge(i,x);add_edge(x,i);
    	}
    	ll ans=0;
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])
    		{
    			cnt=0;
    			get_loop(i);
    //			for(int j=1;j<=cnt;j++)
    //				cout<<loop[j]<<' ';
    //			cout<<endl;
    			for(int i=head[loop[1]];i;i=nxt[i])
    				if(to[i]==loop[cnt])st=i;
    //			cout<<st<<' '<<(st^1)<<endl;
    			dfs(loop[1],0);
    			ll x=f[loop[1]][0];
    			for(int i=head[loop[cnt]];i;i=nxt[i])
    				if(to[i]==loop[1])st=i;
    			memset(f,0,sizeof(f));
    			dfs(loop[cnt],0);
    			ans+=max(x,f[loop[cnt]][0]);
    //			cout<<x<<' '<<f[loop[cnt]][0]<<endl;
    		}
    	write(ans);
    }
    
  • 相关阅读:
    vue通过webpack打包后怎么运行
    vue中请求本地的json数据
    electron打包成桌面应用程序的详细介绍
    Web应用架构-Services
    Web应用架构-Full-text Search Service
    Web应用架构-Job Queue & Servers
    Web应用架构-Caching Service
    Web应用架构-Database
    设计模式:设计模式概述&JDK中的应用
    常见面试问题总结
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11838854.html
Copyright © 2011-2022 走看看