• 5.13 考试修改和总结


    先放题解吧,考的很悲桑

    第一题组合计数类DP

    缩点之后易得对于每个固定形态的树有ans=(s1^d1*s2^d2……)

    然后我们知道把一个树的普吕弗序列乘起来得s1^(d1-1)*s2^(d2-1)……

    然后ans=普吕弗序列乘积*(s1*s2……)

    设普吕弗序列长度为L(题解中的n-2并不标准)

    因为sigma(s)=n

    所以ans=simga(普吕弗序列乘积)*(s1*s2……)

    ans=n^L*(s1*s2……)

    我们只需要求出来sigma((s1*s2……)),dp就可以了

    设f[i][j]表示i个元素分成j个联通块,我们考虑1的连通块大小则有

    f[i][j]=simga(f[i-k][j-1]*C[i-1][k-1]*(m-1)!/2*m))

    其中(m-1)!/2是环内方案数,m是环长

    最后注意不存在二元环以及整个是一个环的情况

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    
    typedef long long LL;
    const int maxn=210;
    int n,mod;
    int C[maxn][maxn];
    int sum[maxn];
    int f[maxn][maxn];
    
    void Get_C(){
    	C[0][0]=1;
    	for(int i=1;i<=n;++i){
    		C[i][0]=C[i][i]=1;
    		for(int j=1;j<i;++j){
    			C[i][j]=C[i-1][j-1]+C[i-1][j];
    			if(C[i][j]>=mod)C[i][j]-=mod;
    		}
    	}return;
    }
    void Get_DP(){
    	sum[1]=1;sum[3]=3;
    	for(int i=4;i<=n;++i)sum[i]=sum[i-1]*i%mod;
    	f[0][0]=1;
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=i;++j){
    			for(int k=1;k<=i;++k){
    				f[i][j]=f[i][j]+1LL*f[i-k][j-1]*C[i-1][k-1]*sum[k]%mod;
    				if(f[i][j]>=mod)f[i][j]-=mod;
    			}
    		}
    	}
    	int ans=1;
    	for(int i=3;i<=n-1;++i)ans=ans*i%mod;
    	int now=1;
    	for(int i=2;i<=n;++i){
    		ans=ans+1LL*f[n][i]*now%mod;
    		if(ans>=mod)ans-=mod;
    		now=now*n%mod;
    	}printf("%d
    ",ans);return;
    }
    
    int main(){
    	freopen("land.in","r",stdin);
    	freopen("land.out","w",stdout);
    	scanf("%d%d",&n,&mod);
    	Get_C();Get_DP();
    	return 0;
    }
    

    至于第二题嘛,首先这是一道论文题,而且还是论文为了引入数位DP算法用的题目

    所以这是一道很简单的题目

    首先设n的长度为len,长度不为len的和很好计算,随便搞一搞就好了

    之后我们考虑n的限制,分奇数偶数讨论

    类似数位DP算贡献

    如果len是偶数,那么每一位的符号是确定的,只需要知道出现的次数就可以了,扫一遍即可

    如果len是奇数,相邻两个数互相抵消,只会剩下1,然后算有多少对就可以了

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    LL n;
    int Num[22],L;
    LL Solve(int n,int k){
    	if(k&1){
    		LL d=-1;
    		for(int i=1;i<=n;++i)d=d*10;
    		return d/2;
    	}else{
    		if(!(n&1))return 0;
    		LL d=-45;
    		for(int i=1;i<n;++i)d=d*10;
    		return d;
    	}
    }
    LL Get_num(LL pre,int n){
    	int len=0,tmp=1;
    	LL p=pre,sum=0;
    	while(p){
    		sum=sum+(p%10)*tmp;
    		tmp=-tmp;len++;p/=10;
    	}sum=sum*(-tmp);
    	for(int i=1;i<=n;++i)sum=sum*10;
    	LL ans=Solve(n,n+len);
    	if(!((n+len)&1))ans+=sum;
    	return ans;
    }
    LL Get_ans(LL n){
    	if(n<10){
    		LL ans=0;
    		for(int i=1;i<=n;++i){
    			if(i&1)ans+=i;
    			else ans-=i;
    		}return ans;
    	}
    	memset(Num,0,sizeof(Num));L=0;
    	LL u=n;
    	while(u)Num[++L]=u%10,u/=10;
    	LL ans=5;
    	for(int i=1;i<L;++i){
    		for(int j=1;j<=9;++j){
    			ans-=Get_num(j,i-1);
    		}
    	}
    	LL pre=0;
    	for(int i=L;i>=2;--i){
    		int end=Num[i];
    		for(int j=0;j<end;++j){
    			if(pre)ans-=Get_num(pre,i-1);
    			pre++;
    		}pre*=10;
    	}
    	int tmp=Num[1];
    	int t=-1;
    	for(int i=0;i<=tmp;++i){
    		memset(Num,0,sizeof(Num));L=0;
    		LL now=pre+i;
    		while(now){
    			Num[++L]=now%10;
    			now/=10;
    		}
    		for(int j=L;j>=1;--j){
    			ans+=Num[j]*t;
    			t=-t;
    		}	
    	}return ans;
    }
    int main(){
    	freopen("count.in","r",stdin);
    	freopen("count.out","w",stdout);
    	while(scanf("%lld",&n)==1){
    		if(!n)break;
    		printf("%lld
    ",Get_ans(n));
    	}return 0;
    }
    

    第三题是个提交答案题,自己失误很大

    首先第一个点爆搜写错了,第三个点没开long long,第十个点标程写错了

    QAQ 一共炸掉了30分,真是悲桑

    但是为什么失误这么大呢,显然是因为自己给题答只留了一个小时多一点的时间,其他时间用来check第二题和磕第一题了

    如果按照CTSC我给题答留个两个多小时的话,应该能搞出50-60分

    而且吐槽一句:这个题答太不标准了,没checker,没评分参数,不然我怎么会挂掉?

    挂掉还是自己弱

    第一个点爆搜就可以了,自己犯蠢挂了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    
    const int maxn=200010;
    int n,m;
    int ans=0;
    int val[maxn];
    struct OP{
    	char type;
    	int u,v,val;
    }c[maxn];
    
    int Get_ans(int S){
    	int ans=0;
    	for(int i=0;i<n;++i)if(S>>i&1)ans+=val[i];
    	for(int i=1;i<=m;++i){
    		int u=c[i].u,v=c[i].v;
    		if(c[i].type=='A'){
    			if(S>>u&1){
    				if(S>>v&1)ans+=c[i].val;
    			}
    		}else if(c[i].type=='B'){
    			if((S>>u&1)||(S>>v&1))ans+=c[i].val;
    		}else if(c[i].type=='C'){
    			if(S>>u&1){
    				if(!(S>>v&1))ans+=c[i].val;
    			}
    		}else if(c[i].type=='D'){
    			if(S>>v&1){
    				if(!(S>>u&1))ans+=c[i].val;
    			}
    		}else{
    			if(!(S>>u&1)){
    				if(!(S>>v&1))ans+=c[i].val;
    			}
    		}
    	}return ans;
    }
    
    int main(){
    	freopen("shell1.in","r",stdin);
    	freopen("shell1.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<n;++i)scanf("%d",&val[i]);
    	for(int i=1;i<=m;++i){
    		c[i].type=getchar();
    		while(c[i].type<'!')c[i].type=getchar();
    		scanf("%d%d%d",&c[i].u,&c[i].v,&c[i].val);
    		c[i].u--;c[i].v--;
    	}
    	for(int i=0;i<(1<<n);++i){
    		ans=max(ans,Get_ans(i));
    	}printf("%d
    ",ans);
    	return 0;
    }
    

    第二个点注意到所有的权都很大,所以只是让你去写高精度

    你贪心的去取所有正权点,会发现所有正权边也会被取到

    然后答案就显然了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    
    const int maxn=52;
    int n,m,u,v;
    char s[maxn];
    struct big_num{
    	int a[52],len;
    	void init(){
    		len=0;memset(a,0,sizeof(a));
    		len=strlen(s+1);
    		for(int i=len;i>=1;--i)a[len-i+1]=s[i]-'0';
    	}
    	void add(const big_num &A){
    		len=max(len,A.len)+1;
    		for(int i=1;i<=len;++i){
    			a[i]=a[i]+A.a[i];
    			if(a[i]>=10)a[i]-=10,a[i+1]++;
    		}
    		while(len>0&&a[len]==0)len--;
    	}
    	void print(){
    		for(int i=len;i>=1;--i)printf("%d",a[i]);
    	}
    }ans,A;
    
    int main(){
    	freopen("shell2.in","r",stdin);
    	freopen("shell2.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%s",s+1);
    		if(s[1]=='-')continue;
    		A.init();ans.add(A);
    	}
    	for(int i=1;i<=m;++i){
    		char ch=getchar();
    		while(ch<'!')ch=getchar();
    		scanf("%d%d",&u,&v);
    		scanf("%s",s+1);
    		if(s[1]=='-')continue;
    		A.init();ans.add(A);
    	}ans.print();
    	return 0;
    }
    

    第三个点你会发现边权都特别大,然后点权是-1

    然后限制都是B,所以我们一定能取得所有的边,问题就转化成了用最少的点

    限制是u,v两个之中至少有一个被选中,二分图匹配即可

    注意开long long

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    typedef long long LL;
    const int maxn=200010;
    int n,m,u,v,w;
    LL ans=0;
    int val[maxn];
    int h[maxn],cnt=1;
    int vis[maxn],tim;
    int girl[maxn];
    struct edge{
    	int to,next;
    }G[3000010];
    void add(int x,int y){
    	++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;
    }
    bool find(int u){
    	for(int i=h[u];i;i=G[i].next){
    		int v=G[i].to;
    		if(vis[v]==tim)continue;
    		vis[v]=tim;
    		if(!girl[v]||find(girl[v])){
    			girl[v]=u;girl[u]=v;
    			return true;
    		}
    	}return false;
    }
    
    int main(){
    	freopen("shell3.in","r",stdin);
    	freopen("shell3.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%d",&val[i]);
    	for(int i=1;i<=m;++i){
    		char ch=getchar();
    		while(ch<'!')ch=getchar();
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v);add(v,u);
    		ans+=w;
    	}
    	for(int i=1;i<=n;++i){
    		if(girl[i])continue;
    		tim++;
    		if(find(i))ans--;
    	}printf("%lld
    ",ans);
    	return 0;
    }
    

    第四个点只有C限制,而且边权都很小且是负数

    我们就发现我们一条边也不能选,限制变成了选u就必须选v,求最大点权和

    最大权闭合子图即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<queue>
    using namespace std;
    
    const int maxn=200010;
    const int oo=0x7fffffff/3;
    int n,m,S,T;
    int u,v,w;
    int ans=0;
    int val[maxn];
    int h[maxn],cnt=1;
    int cur[maxn];
    struct edge{
    	int to,next,w;
    }G[3000010];
    queue<int>Q;
    int vis[maxn];
    void add(int x,int y,int z){
    	cnt++;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt;
    	++cnt;G[cnt].to=x;G[cnt].next=h[y];G[cnt].w=0;h[y]=cnt;
    }
    bool BFS(){
    	for(int i=S;i<=T;++i)vis[i]=-1;
    	Q.push(S);vis[S]=1;
    	while(!Q.empty()){
    		int u=Q.front();Q.pop();
    		for(int i=h[u];i;i=G[i].next){
    			int v=G[i].to;
    			if(G[i].w>0&&vis[v]==-1){
    				vis[v]=vis[u]+1;
    				Q.push(v);
    			}
    		}
    	}return vis[T]!=-1;
    }
    int DFS(int x,int f){
    	if(x==T||f==0)return f;
    	int w,used=0;
    	for(int i=cur[x];i;i=G[i].next){
    		if(vis[G[i].to]==vis[x]+1){
    			w=f-used;
    			w=DFS(G[i].to,min(G[i].w,w));
    			G[i].w-=w;G[i^1].w+=w;
    			if(G[i].w>0)cur[x]=i;
    			used+=w;if(used==f)return used;
    		}
    	}
    	if(!used)vis[x]=-1;
    	return used;
    }
    void dinic(){
    	while(BFS()){
    		for(int i=S;i<=T;++i)cur[i]=h[i];
    		ans-=DFS(S,oo);
    	}return;
    }
    int main(){
    	freopen("shell4.in","r",stdin);
    	freopen("shell4.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%d",&val[i]);
    	for(int i=1;i<=m;++i){
    		char ch=getchar();
    		while(ch<'!')ch=getchar();
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,oo);
    	}
    	S=0;T=n+1;
    	for(int i=1;i<=n;++i){
    		if(val[i]>0)ans+=val[i],add(S,i,val[i]);
    		else add(i,T,-val[i]);
    	}
    	dinic();
    	printf("%d
    ",ans);
    	return 0;
    }
    

    第五个点我们观察数据会发现有一个点点权很大,一个点点权很小,其他点都是0

    之后看边权,发现边权和都是负的,证明负的点权一定不能取

    且正点权一定能取,由于边权都是负数,所以能不选就不选

    因为全是C操作

    可以把正权点看成S,负权点看成T,从S到T求最小割即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<queue>
    using namespace std;
    
    const int maxn=200010;
    const int oo=0x7fffffff;
    int n,m,S,T;
    int u,v,w;
    int ans;
    int val[maxn];
    int h[maxn],cnt=1;
    int cur[maxn];
    struct edge{
    	int to,next,w;
    }G[3000010];
    queue<int>Q;
    int vis[maxn];
    void add(int x,int y,int z){
    	++cnt;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt;
    	++cnt;G[cnt].to=x;G[cnt].next=h[y];G[cnt].w=0;h[y]=cnt;
    }
    bool BFS(){
    	for(int i=1;i<=n;++i)vis[i]=-1;
    	Q.push(S);vis[S]=1;
    	while(!Q.empty()){
    		int u=Q.front();Q.pop();
    		for(int i=h[u];i;i=G[i].next){
    			int v=G[i].to;
    			if(G[i].w>0&&vis[v]==-1){
    				vis[v]=vis[u]+1;
    				Q.push(v);
    			}
    		}
    	}return vis[T]!=-1;
    }
    int DFS(int x,int f){
    	if(x==T||f==0)return f;
    	int w,used=0;
    	for(int i=cur[x];i;i=G[i].next){
    		if(vis[G[i].to]==vis[x]+1){
    			w=f-used;
    			w=DFS(G[i].to,min(G[i].w,w));
    			G[i].w-=w;G[i^1].w+=w;
    			if(G[i].w>0)cur[x]=i;
    			used+=w;if(used==f)return used;
    		}
    	}
    	if(!used)vis[x]=-1;
    	return used;
    }
    void dinic(){
    	while(BFS()){
    		for(int i=1;i<=n;++i)cur[i]=h[i];
    		ans-=DFS(S,oo);
    	}return;
    }
    
    int main(){
    	freopen("shell5.in","r",stdin);
    	freopen("shell5.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&val[i]);
    		if(val[i]>0)ans+=val[i];
    	}
    	for(int i=1;i<=m;++i){
    		char ch=getchar();
    		while(ch<'!')ch=getchar();
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,-w);
    	}
    	S=12345;T=98765;
    	dinic();
    	printf("%d
    ",ans);
    	return 0;
    }
    

    UPD:第九个点和第五个点一样,所以程序差不多

    第六个点我们发现数据时完全随机无规律,所以只能用近似算法了

    模拟退火乱搞即可,搞的并没有答案优QAQ

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define eps 1e-5
    using namespace std;
    
    const int maxn=200010;
    const int oo=0x7fffffff;
    int n,m,ans;
    int val[maxn];
    bool vis[maxn];
    struct OP{
    	char type;
    	int u,v,val;
    }c[maxn];
    double R(){return rand()%10000/10000.0;}
    int Get_ans(){
    	int sum=0;
    	for(int i=1;i<=n;++i)if(vis[i])sum+=val[i];
    	for(int i=1;i<=m;++i){
    		int u=c[i].u,v=c[i].v;
    		if(c[i].type=='A'){
    			if(vis[u]&&vis[v])sum+=c[i].val;
    		}else if(c[i].type=='B'){
    			if(vis[u]||vis[v])sum+=c[i].val;
    		}else if(c[i].type=='C'){
    			if(vis[u]&&!vis[v])sum+=c[i].val;
    		}else if(c[i].type=='D'){
    			if(!vis[u]&&vis[v])sum+=c[i].val;
    		}else if(!vis[u]&&!vis[v])sum+=c[i].val;
    	}return sum;
    }
    void SA(double T){
    	int tmp=0,cur=0;
    	for(int i=1;i<=n;++i)vis[i]=rand()%2;
    	cur=Get_ans();
    	while(T>eps){
    		int now=rand()%n+1;
    		vis[now]^=1;
    		tmp=Get_ans();
    		ans=max(ans,tmp);
    		int d=tmp-cur;
    		if(d>0||exp(d/T)>R())cur=tmp;
    		else vis[now]^=1;
    		T*=0.998;
    	}return;
    }
    
    int main(){
    	freopen("shell6.in","r",stdin);
    	freopen("shell6.out","w",stdout);
    	srand(5211314);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%d",&val[i]);
    	for(int i=1;i<=m;++i){
    		c[i].type=getchar();
    		while(c[i].type<'!')c[i].type=getchar();
    		scanf("%d%d%d",&c[i].u,&c[i].v,&c[i].val);	
    	}
    	int T=1000;ans=-oo;
    	while(T--)SA(10000);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    第七个点和第八个点数据都做错了,不过我还是写了标程的

    很容易发现他想要做的数据是分块的,然后分块模拟退火即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define eps 1e-5
    using namespace std;
    
    const int maxn=200010;
    const int oo=0x7fffffff;
    int n,m,ans,Ans;
    int val[maxn];
    bool vis[maxn];
    struct OP{
    	char type;
    	int u,v,val;
    }c[maxn];
    double R(){return rand()%10000/10000.0;}
    int Get_ans(){
    	int sum=0;
    	for(int i=1;i<=100;++i)if(vis[i])sum+=val[i];
    	for(int i=1;i<=m;++i){
    		int u=c[i].u,v=c[i].v;
    		if(c[i].type=='A'){
    			if(vis[u]&&vis[v])sum+=c[i].val;
    		}else if(c[i].type=='B'){
    			if(vis[u]||vis[v])sum+=c[i].val;
    		}else if(c[i].type=='C'){
    			if(vis[u]&&!vis[v])sum+=c[i].val;
    		}else if(c[i].type=='D'){
    			if(!vis[u]&&vis[v])sum+=c[i].val;
    		}else if(!vis[u]&&!vis[v])sum+=c[i].val;
    	}return sum;
    }
    void SA(double T){
    	int tmp=0,cur=0;
    	for(int i=1;i<=100;++i)vis[i]=rand()%2;
    	cur=Get_ans();
    	while(T>eps){
    		int now=rand()%100+1;
    		vis[now]^=1;
    		tmp=Get_ans();
    		ans=max(ans,tmp);
    		int d=tmp-cur;
    		if(d>0)cur=tmp;
    		else vis[now]^=1;
    		T*=0.9;
    	}return;
    }
    
    int main(){
    	freopen("shell7.in","r",stdin);
    	freopen("shell7.out","w",stdout);
    	srand(5211314);
    	scanf("%d%d",&n,&m);
    	m/=1000;
    	for(int i=1;i<=n;++i)scanf("%d",&val[i]);
    	for(int k=1;k<=1000;++k){
    		for(int i=1;i<=m;++i){
    			c[i].type=getchar();
    			while(c[i].type<'!')c[i].type=getchar();
    			scanf("%d%d%d",&c[i].u,&c[i].v,&c[i].val);
    			c[i].u=c[i].u%100+1;c[i].v=c[i].v%100+1;	
    		}
    		ans=-oo;int T=300;
    		while(T--)SA(10000);
    		Ans+=ans;
    		for(int i=1;i+100<=n;++i)val[i]=val[i+100];
    	}
    	printf("%d
    ",Ans);
    	return 0;
    }
    

    第十个点m=n-1,观察边很容易发现这是棵树

    设f[i][0/1]表示选不选,然后做一遍树形DP就可以了

    讨论的时候注意细节,连std都讨论错了

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int maxn=200010;
    int n,m;
    int u,v,w;
    int h[maxn],cnt=0;
    int val[maxn];
    LL f[maxn][2];
    struct edge{
    	char type;
    	int to,next,w;
    }G[maxn];
    void add(int x,int y,int z,char c){
    	cnt++;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;G[cnt].type=c;h[x]=cnt;
    }
    void DP(int u){
    	f[u][0]=0;f[u][1]=val[u];
    	for(int i=h[u];i;i=G[i].next){
    		int v=G[i].to;
    		DP(v);
    		if(G[i].type=='A'){
    			f[u][0]=f[u][0]+max(f[v][0],f[v][1]);
    			f[u][1]=f[u][1]+max(f[v][0],f[v][1]+G[i].w);
    		}else if(G[i].type=='B'){
    			f[u][0]=f[u][0]+max(f[v][0],f[v][1]+G[i].w);
    			f[u][1]=f[u][1]+G[i].w+max(f[v][0],f[v][1]);
    		}else if(G[i].type=='C'){
    			f[u][0]=f[u][0]+max(f[v][0],f[v][1]);
    			f[u][1]=f[u][1]+max(f[v][0]+G[i].w,f[v][1]);
    		}else if(G[i].type=='D'){
    			f[u][0]=f[u][0]+max(f[v][0],f[v][1]+G[i].w);
    			f[u][1]=f[u][1]+max(f[v][0],f[v][1]);
    		}else{
    			f[u][0]=f[u][0]+max(f[v][0]+G[i].w,f[v][1]);
    			f[u][1]=f[u][1]+max(f[v][1],f[v][0]);
    		}
    	}return;
    }
    
    int main(){
    	freopen("shell10.in","r",stdin);
    	freopen("shell10.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%d",&val[i]);
    	for(int i=1;i<=m;++i){
    		char ch=getchar();
    		while(ch<'!')ch=getchar();
    		scanf("%d%d%d",&u,&v,&w);
    		if(u>v){
    			swap(u,v);
    			if(ch=='B')ch='C';
    			else if(ch=='C')ch='B';
    		}
    		add(u,v,w,ch);
    	}
    	DP(1);
    	printf("%lld
    ",max(f[1][0],f[1][1]));
    	return 0;
    }
    

      

  • 相关阅读:
    深入理解JVM(二)--对象的创建
    深入理解JVM(一) -- 自动内存管理机制
    代理模式(Proxy)
    心知天气数据API 产品的高并发实践
    Jenkins 构建踩坑经历
    log4net SmtpAppender 踩坑总结
    从 ASP.NET Core 2.1 迁移到 2.2 踩坑总结
    在Windows上安装 Consul
    redis-desktop-manager 0.9.3 安装(最后一个免费版本)
    在Windows上安装Redis
  • 原文地址:https://www.cnblogs.com/joyouth/p/5489945.html
Copyright © 2020-2023  润新知