R5暴力AK赛(NOIP模拟赛)/省选专练HAOI2015树上染色




这真的算NOIP?

我还是退役了吧

100+100+20

T1:看似水题,但是超时是很有可能的。

他是判断一个数是不是斐波拉切数列的前n项和

利用牛顿迭代可以一次求出sqrt然后向下取整判断

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
using namespace std;
typedef int INT;
//#define int long long
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int n;
int main(){
	freopen("ape.in","r",stdin);
	freopen("ape.out","w",stdout);
	read(n);
	for(register int i=1;i<=n;++i){
		int x;
		read(x);
		int sum=(int)sqrt((x-1)*2);
//		cout<<sum<<" ";
		if(((sum*(sum+1))/2)==x-1){
			puts("1");
		}
		else{
//			cout<<sum<<" "<<((sum*(sum+1))/2)<<" ";
			puts("0");	
		} 
	}
	return 0;
}

T2树形DP:HAOI2015树上染色

一个标准且典型的枚举边的代价

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef int INT;
#define int long long 
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
const int N=2100+1;
const int K=2100;
struct Front_star{
	int u,v,w,nxt;
}e[N*3];
int cnt=1;
int first[N]={};
void add(int u,int v,int w){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
int n,k;
int dp[N][K]={};
int siz[N]={};
int vis[N]={};
int getsiz(int u,int fat){
	siz[u]=1;
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(v==fat)continue;
		siz[u]+=getsiz(v,u);
	}
	return siz[u];
}
void dfs(int u,int w){
//	cout<<u<<'\n';
	vis[u]=1;
	int siznow=0;
	memset(dp[u],-1,sizeof(dp[u]));
	dp[u][0]=0;
//	cout<<u<<'\n';
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		int w=e[i].w;
//		cout<<u<<" "<<v<<" "<<w<<'\n';
		if(!vis[v]){
			dfs(v,w);
			siznow+=siz[v];
			for(int j=min(k,siznow);j>=0;j--){
//				cout<<u<<" : "<<j<<'\n';
				int r=min(j,min(siz[v],k));
				for(int k=0;k<=r;k++){
					if(dp[u][j-k]!=-1){
						dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
					}
				}
			}
		}
	}
	int remain=max(siz[u]+k-n,(int)1);
	for(int i=min(k,siz[u]);i>=remain;i--){
		int wnow=w*(k-i)*i+w*(n-siz[u]-k+i)*(siz[u]-i);//left k-i right i
		dp[u][i]=max(dp[u][i],dp[u][i-1])+wnow;
	}
	dp[u][0]+=w*(n-siz[u]-k)*(siz[u]);//left k right 0
}
INT main(){
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
//cout<<"here";
	read(n);
	read(k);
	for(int i=1;i<n;i++){
		int u,v,w;
		read(u);
		read(v);
		read(w);
		add(u,v,w);
		add(v,u,w);
	}
	siz[1]=getsiz(1,0);
	dfs(1,0);
	cout<<dp[1][k];
//	cout<<max(dp[1][k][0],dp[1][k][1]);
	return 0;
}

T3神仙题

看见割你需要想到对偶图

但是这有什么用

一个对偶图中的点选不上实际是边成环。

因为对偶图中的点是一个点块。

如果S,T在点块内那么他们都可以连通

否则不行

转化来到了:NOIP2017Day2T1

并查集判环(或者叫做判连通)

暴力代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
//int idx[N][N]={};
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
const int N=51;
struct Front_star{
	int u,v,nxt;
}e[N*N*2];
int cnt=1;
int first[N*N]={};
void add(int u,int v){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
int idx[N][N];
int del[N*N][N*N]={};
int vis[N*N];
int n,k;
int lastans=1;
void dfs(int u,int goal){
	vis[u]=1;
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(vis[v])continue;
		if(del[u][v]||del[v][u])continue;
		dfs(v,goal);
	}
}
void check(int from,int goal){
//	cout<<"in"<<'\n';
	memset(vis,0,sizeof(vis));
	vis[from]=1;
	dfs(from,goal);
	if(vis[goal]){
		lastans=1;
	}
	else{
		lastans=0;
	}
	if(lastans==1){
		puts("TAK");
	}
	else{
		puts("NIE");
	}
}
int main(){
	freopen("rain.in","r",stdin);
	freopen("rain.out","w",stdout);
	read(n);
	read(k);
	int idx_cnt=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			idx[i][j]=++idx_cnt;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i>1){
				add(idx[i][j],idx[i-1][j]);
			}
			if(i<n){
				add(idx[i][j],idx[i+1][j]);
			}
			if(j>1){
				add(idx[i][j],idx[i][j-1]);
			}
			if(j<n){
				add(idx[i][j],idx[i][j+1]);
			}
		}
	}
//	cout<<"------"<<'\n';
	for(int i=1;i<=k;i++){
		int u1,v1,u2,v2;
		char c1[2],c2[2];
		scanf("%d%d%s%d%d%s",&u1,&v1,c1,&u2,&v2,c2);
//		cout<<"----"<<'\n';
		if(lastans==1){
			if(c1[0]=='E'){
				del[idx[u1][v1]][idx[u1+1][v1]]=1;
				check(idx[u1][v1],idx[u1+1][v1]); 
			}
			else{
				del[idx[u1][v1]][idx[u1][v1+1]]=1;
				check(idx[u1][v1],idx[u1][v1+1]);
			}
		}
		else{
			if(c2[0]=='E'){
				del[idx[u2][v2]][idx[u2+1][v2]]=1;
				check(idx[u2][v2],idx[u2+1][v2]);
			}
			else{
				del[idx[u2][v2]][idx[u2][v2+1]]=1;
				check(idx[u2][v2],idx[u2][v2+1]);
			}			
		}
	}
//	for(int i=1;i<=n*n;i++){
//		for(int j=1;j<=n*n;j++){
//			cout<<del[i][j]<<" ";
//		}
//		cout<<'\n'; 
//	}
	return 0;
}

std

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int n,k;
int idx[1505][1505]={};
int fa[1505*1505+10]={};
int idx_cnt=1;
int lastans=1;
//inline int getfa(int x){
//    int a=x,c;
//    while(x!=fa[x])x=fa[x];
//    while(x!=(c=fa[a]))fa[a]=x,a=c;
//    return x;
//}
int getfa(int x){
	if(fa[x]==x)return x;
	else return fa[x]=getfa(fa[x]);
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<n;i++){
		for(int j=1;j<n;j++){
			fa[idx_cnt]=idx[i][j]=idx_cnt++;
		}
	}
	while(k--){
		int u1,v1,u2,v2;
		char s1[2];
		char s2[2];
		scanf("%d%d%s%d%d%s",&u1,&v1,s1,&u2,&v2,s2);
		if(lastans==0){
			u1=u2;
			v1=v2;
			s1[0]=s2[0];
		}
		if(s1[0]=='E'){
			int a=getfa(idx[u1][v1]);
			int b=getfa(idx[u1][v1-1]);
			if(lastans=(a!=b))fa[a]=b;
		}
		else{
			int a=getfa(idx[u1][v1]);
			int b=getfa(idx[u1-1][v1]);
			if(lastans=(a!=b))fa[a]=b;
		}
		if(lastans==1)puts("TAK");
		else puts("NIE");
	}
}

转载于:https://www.cnblogs.com/Leo-JAM/p/10079228.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值