zoukankan      html  css  js  c++  java
  • 8-22模拟赛解题报告

    考场上T2想到正解,却没时间打,死磕在T1,心好累(DeBug下午+晚上。


    T1 欠款

    题目大意:(n)个人互相欠款,求还款的最小次数。((nle 23))

    这题比较特别,是一个基本 (不会的) 状压DP,考场上打了一个(floied)骗了(80)分左右。

    因为一个连通块内如果欠款数之和正好为(0),说明该连通块是可以自己做好不需要他人参与的,所以(f[i])表示该状态下联通块的最大数量,每次加入一个点更新,最后用(n-f[2^n-1])就是答案。

    小结:

    解题关键:想到状压DP状态

    芝士点:状压DP

    整体来说不算太难,考场想错方向了。

    手起,码落:

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define re register
    using namespace std;
    const int N=25;
    inline int read()
    {
    	re int x=0,f=1;
    	re char ch=getchar();
    	for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f*=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    	return x*f;
    }
    int n,m,val[N],f[(1<<N)+5];
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(re int i=1,u,v,Val;i<=m;i++)
    	{
    		u=read(),v=read(),Val=read();
    		val[u]+=Val,val[v]-=Val;
    	}
    	for(re int i=1,sum=0;i<(1<<n);i++,sum=0)
    	{
    		for(re int j=0;j<n;j++)
    			if(i&(1<<j))
    				f[i]=max(f[i],f[i-(1<<j)]),sum+=val[j+1];
    		f[i]+=(sum==0);
    	}
    	printf("%d",n-f[(1<<n)-1]);
    	return 0;
    }
    

    T2:子树

    题目大意: 一棵树取两棵子树,求两颗子树的最大权值和。

    还是比较好想的,建虚点把基环树变成普通树来做,然后就是基本换根DP了。

    手起,码落:

    #include<bits/stdc++.h>
    #define re register
    #define inf 1e18
    #define max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    const int N=1000005;
    inline int read()
    {
    	re int x=0,f=1;
    	re char ch=getchar();
    	for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f*=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    	return x*f;
    }
    struct edge{int v,net;}e[N<<1];
    int T,n,m,cnt,hd[N],s,in[N],fa[N];
    long long m1[N],m2[N],ans,ma_son[N],ma_down[N],ma_up[N],sum[N],a[N];
    bool vis[N];
    inline void add(int u,int v)
    {
    	in[u]++,in[v]++;
    	e[++cnt].v=v,e[cnt].net=hd[u],hd[u]=cnt;
    	e[++cnt].v=u,e[cnt].net=hd[v],hd[v]=cnt;
    }
    queue <int> q;
    inline void topu()
    {
    	for(;!q.empty();q.pop());
    	for(re int i=1;i<=n;i++)
    		if(in[i]==1)q.push(i),in[i]--;
    	for(re int u;!q.empty();)
    	{
    		u=q.front();q.pop();
    		for(re int v,i=hd[u];i;i=e[i].net)
    		{
    			v=e[i].v;
    			if(in[v]==0)continue;
    			in[v]--;
    			if(in[v]==1)q.push(v);
    		}
    	}
    	for(re int u=1;u<=n;u++)
    	{
    		if(in[u]!=2)continue;
    		vis[u]=1,add(u,s);
    	}
    }
    void first(int u)
    {
    	ma_son[u]=sum[u]=a[u];
    	for(re int v,i=hd[u];i;i=e[i].net)
    	{
    		v=e[i].v;
    		if(v==fa[u]||(vis[v]&vis[u]))continue;
    		fa[v]=u,first(v);
    		sum[u]+=sum[v];
    		if(sum[v]>0)ma_son[u]+=sum[v];
    	}
    	if(u==s)ma_son[u]=-inf;
    	m1[u]=m2[u]=-inf;
    	for(re int v,i=hd[u];i;i=e[i].net)
    	{
    		v=e[i].v;
    		if(v==fa[u]||(vis[v]&vis[u]))continue;
    		if(ma_down[v]>m1[u])m2[u]=m1[u],m1[u]=ma_down[v];
    		else if(m1[v]>m2[u])m2[u]=ma_down[v];
    	}
    	ma_down[u]=max(ma_son[u],m1[u]);
    }
    void dfs(int u)
    {
    	for(re int v,i=hd[u];i;i=e[i].net)
    	{
    		v=e[i].v;
    		if(fa[u]==v||(vis[u]&&vis[v]))continue;
    		if(u==s)ma_up[v]=-inf;
    		else ma_up[v]=ma_son[u]+(sum[1]-sum[u]<=0?0:sum[1]-sum[u])-(sum[v]<=0?0:sum[v]);
    		if(fa[u]!=-1)ma_up[v]=max(ma_up[v],ma_up[u]);
    		if(ma_down[v]==m1[u])ma_up[v]=max(ma_up[v],m2[u]);
    		else ma_up[v]=max(ma_up[v],m1[u]);
    		dfs(v);
    	}
    	if(u==s)return ;
    	if(fa[u]!=-1)ans=max(ans,ma_son[u]+ma_up[u]);
    	for(re int v,i=hd[u];i;i=e[i].net)
    	{
    		v=e[i].v;
    		if(fa[u]==v||(vis[v]&&vis[u]))continue;
    		ans=max(ans,ma_son[u]+ma_down[v]-(sum[v]<=0?0:sum[v])+(sum[1]-sum[u]<=0?0:sum[1]-sum[u]));
    	}
    }
    int main()
    {
    	scanf("%d",&T);
    	for(;T--;)
    	{
    		memset(hd,0,sizeof(hd)),cnt=0,ans=-inf;
    		memset(fa,0,sizeof(fa));
    		memset(vis,0,sizeof(vis));
    		memset(in,0,sizeof(in));
    		scanf("%d%d",&n,&m);s=1+n;
    		for(re int i=1;i<=n;i++)scanf("%lld",&a[i]);
    		for(re int i=1;i<=m;i++)add(read(),read());
    		if(n==m)topu();
    		fa[1]=-1;
    		first(1);
    		dfs(1);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    写的好简洁呀!咕咕咕~

  • 相关阅读:
    Centos7下安装7za 及7za常用命令
    n2n搭建手记-2-V2
    n2n搭建手记-1-V1
    centos 7 下发送邮件设置
    Centos7 下安装mysql
    C#设计模式之11:命令模式
    asp.net core实时库:SignalR(1)
    asp.net core 排序过滤分页组件:sieve(2)表达式树的复习
    asp.net core 排序过滤分页组件:sieve
    linux上面sqlserver数据库的操作
  • 原文地址:https://www.cnblogs.com/jkzcr01-QAQ/p/13574126.html
Copyright © 2011-2022 走看看