csp-s模拟6

A. 一般图最小匹配

\(m\) 小于 \(\frac{n}{2}\) 所以对原数组排序后做差分,差分后的数不能选相邻的,设 \(f_{i,j,0/1}\) 表示前 \(i\) 个,选了 \(j\) 个,第 \(i\) 个选没选

直接 \(dp\) 求最小值就行

点击查看代码
#include<bits/stdc++.h>
const int maxn=5001;
using namespace std;
int n,m,a[maxn],d[maxn];
long long f[maxn][2501][2];

int main()
{
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	sort(a+1,a+1+n);n--;
	for(int i=1;i<=n;i++)
		d[i]=a[i+1]-a[i];
		
	for(int i=0;i<=n;i++) 
		for(int j=0;j<=m;j++) 
			f[i][j][0]=f[i][j][1]=1e15;
			
	f[1][1][1]=d[1],f[1][0][0]=0;
	for(int i=2;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0],f[i-1][j][1]));
			if(j!=0)f[i][j][1]=min(f[i][j][1],f[i-1][j-1][0]+d[i]);
//			cout<<i<<" "<<j<<" "<<f[i][j][1]<<" "<<f[i][j][0]<<endl;
		}
	}
	cout<<min(f[n][m][0],f[n][m][1]);

	return 0;
}
/*
4 1
2 4 7 3

8 3
9 2 3 12 11 7 6 5
*/

B. 重定向

大型分讨,我思路是考虑 \(1\) 和第一个 \(0\),然后再向下细分是否考虑第一个使字典序变小的数,细节很多,5.8k代码,不建议观看

点击查看代码
#include<bits/stdc++.h>
#define int long long
const int maxn=1e6+10;
using namespace std;
int t,n,a[maxn],d[maxn],cnt,tem[maxn];
bool vis[maxn];

signed main()
{
//	freopen("test.in","r",stdin);
//	freopen("ans.out","w",stdout);
	freopen("repeat.in","r",stdin);
	freopen("repeat.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		int flag=0,flag2=0;
		cin>>n;
		fill(vis,vis+1+n,0);
		fill(d,d+1+n,0);
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			if(a[i]==0) flag2=1;
			vis[a[i]]=1;
			if(a[i]==1) flag=1;
		} 
		if(!flag2)
		{
			for(int i=1;i<=n;i++)
			{
				if(a[i]>a[i+1])
				{
					a[i]=0;
					flag2=1;
					break;
				}
			}
			for(int i=1;i<=n-(flag2==0);i++)
				if(a[i]) cout<<a[i]<<" ";
			cout<<'\n';
			continue;
		}
		cnt=0;
		for(int i=1;i<=n;i++) if(!vis[i]) d[++cnt]=i;
		if(flag)
		{
//			cout<<"!";
			for(int i=1;i<=n;i++)
			{
				if(a[i]==1)
				{
					flag=0;
					break;
				}
				if(a[i]==0)break;
			}
			if(flag)
			{
				for(int i=1;a[i]!=0;i++)
				{
					if(a[i]>d[1]||(a[i]>a[i+1]&&a[i+1])) 
					{
						flag=0;
						break;
					}
				}
				if(flag)
				{
//					cout<<"!";
					cnt=-1;
					for(int i=1;i<=n;i++) if(a[i]==1) a[i]=-1;
					d[0]=1;
					for(int i=1;i<=n;i++)
					{
						if(a[i]==0) a[i]=d[++cnt];
					}
					for(int i=1;i<=n;i++)
					{
						if(a[i]!=-1) cout<<a[i]<<" ";
					}
					cout<<'\n';	
				}
				else
				{
//					cout<<"!";
					int temp=0;
					for(int i=1;a[i]!=0;i++)
					{
						if(a[i]>d[1]&&a[i]>d[0]||(a[i]>a[i+1]&&a[i+1]))
						{
//							d[0]=a[i];
							tem[++temp]=i;
//							break;
						}
					}
//					cout<<temp<<endl;
					if(!temp)
					{
						int s=0;
						for(int i=1;i<=n;i++)
							if(!a[i]) a[i]=-d[++s];
						for(int i=1;i<n;i++) 
							if(abs(a[i])>abs(a[i+1]))
							{
								d[0]=abs(a[i]);
								a[i]=0;
								sort(d,d+1+cnt);
								break;
							}
						int num=unique(d,d+1+cnt)-d-1;
						cnt=num;
						cnt=-1;
						if(!d[0])cnt++,a[n]=0;
						for(int i=1;i<=n;i++)
							if(a[i]<0) a[i]=d[++cnt];
						for(int i=1;i<=n;i++)
						{
							if(a[i])cout<<a[i]<<" ";
						}
						cout<<'\n';
					}
					else
					{
						for(int i=1;i<=temp;i++)
							if(a[tem[i]]>a[tem[i]+1])
							{
//								cout<<tem[i]<<" "<<tem[i]+1<<endl;
								temp=tem[i];
								d[0]=a[tem[i]];
								break;
							}
						a[temp]=-1;
						sort(d,d+1+cnt);
						int num=unique(d,d+1+cnt)-d-1;
						cnt=num;
						cnt=-1;
						for(int i=1;i<=n;i++)
						{
							if(a[i]==0) a[i]=d[++cnt];
						}
						for(int i=1;i<=n;i++)
						{
							if(a[i]!=-1)cout<<a[i]<<" ";
						}
						cout<<'\n';	
					}
				}
			}
			else
			{
//				cout<<"!";
				int s=0;
				for(int i=1;i<=n;i++)
					if(!a[i]) a[i]=-d[++s];
				for(int i=1;i<n;i++) 
					if(abs(a[i])>abs(a[i+1]))
					{
						s=i;
						break;
					}
				int minn=1e9,sum=0; 
				for(int i=1;i<=n;i++) if(a[i]<0) a[i]=0;
				for(int i=s+(s==0);i<=n;i++)
				{
					if(a[i])minn=min(minn,a[i]);
				}
				while(!a[s])s++;
				for(int i=1;i<s;i++) 
				{
					if(!a[i])sum++;
					if(minn<d[sum]) break;
					if(a[i]>minn)
					{
						sum=0;
						break;
					}
				}
//				cout<<minn<<endl;
				if(minn<d[sum]&&a[1]==1)
				{
//					cout<<"!";
//					cout<<sum<<endl;
					for(int i=1;i<=n;i++)
					{
						if(a[i]==minn) 
						{
							d[0]=a[i];
							a[i]=-1;
							sort(d,d+cnt+1);
							break;
						}
					}
					cnt=-1;
					for(int i=1;i<=n;i++)
					{
						if(!a[i])a[i]=d[++cnt];
					}
					for(int i=1;i<=n;i++)
					{
						if(a[i]!=-1)cout<<a[i]<<" ";
					}
					cout<<'\n';
				}
				else
				{
					int s=0;
					for(int i=1;i<=n;i++)
						if(!a[i]) a[i]=-d[++s];
					for(int i=1;i<n;i++) 
						if(abs(a[i])>abs(a[i+1]))
						{
							d[0]=abs(a[i]);
							a[i]=0;
							sort(d,d+1+cnt);
							break;
						}
					int num=unique(d,d+1+cnt)-d-1;
					cnt=num;
					cnt=-1;
					if(!d[0])cnt++,a[n]=0;
					for(int i=1;i<=n;i++)
						if(a[i]<0) a[i]=d[++cnt];
					for(int i=1;i<=n;i++)
					{
						if(a[i])cout<<a[i]<<" ";
					}
					cout<<'\n';
				}
			}
		}
		else
		{
//			cout<<"!";
			int s=0;
			for(int i=1;i<=n;i++)
				if(!a[i]) a[i]=-d[++s];
			for(int i=1;i<n;i++) 
				if(abs(a[i])>abs(a[i+1]))
				{
					s=i;
					break;
				}
			int minn=1e9,sum=0; 
			for(int i=1;i<=n;i++) if(a[i]<0) a[i]=0;
			for(int i=s+(s==0);i<=n;i++)
			{
				if(a[i])minn=min(minn,a[i]);
			}
			while(!a[s])s++;
			for(int i=1;i<s;i++) 
			{
				if(a[i]==minn) break;
				if(!a[i])sum++;
				if(minn<d[sum]) break;
				if(a[i]>d[sum+1])
				{
					sum=0;
					break;
				}
			}
//			cout<<minn<<" "<<sum<<endl;
			if(minn<d[sum]&&a[1]==0)
			{
//				cout<<"!";
				for(int i=1;i<=n;i++)
				{
					if(a[i]==minn) 
					{
						d[0]=a[i];
						a[i]=-1;
						sort(d,d+cnt+1);
						break;
					}
				}
				cnt=-1;
				for(int i=1;i<=n;i++)
				{
					if(!a[i])a[i]=d[++cnt];
				}
				for(int i=1;i<=n;i++)
				{
					if(a[i]!=-1)cout<<a[i]<<" ";
				}
				cout<<'\n';
			}
			else
			{
//				cout<<"!";
				int s=0;
				for(int i=1;i<=n;i++)
					if(!a[i]) a[i]=-d[++s];
				for(int i=1;i<n;i++) 
					if(abs(a[i])>abs(a[i+1]))
					{
						d[0]=abs(a[i]);
						a[i]=0;
						sort(d,d+1+cnt);
						break;
					}
				int num=unique(d,d+1+cnt)-d-1;
				cnt=num;
				cnt=-1;
				if(!d[0])cnt++,a[n]=0;
				for(int i=1;i<=n;i++)
					if(a[i]<0) a[i]=d[++cnt];
				for(int i=1;i<=n;i++)
				{
					if(a[i])cout<<a[i]<<" ";
				}
				cout<<'\n';
			}
		}
	}

	return 0;
}
/*
3
2
1 0 
2
0 1 
1
11
9 7 5 11 0 3 4 6 8 1 2   


*/

C. 斯坦纳树

牛牛方法错误当且仅当存在一个点不是关键点但他连了大于等于三个关键点的边,这样会导致有的边按牛牛方法求被重复算

倒着删点,如果这个点有大于等于三条边,那他就会导致做法错误,然后把与他相连的边删了,如果有一个之前被删的会导致

错误的点在这个点被删后不会导致错误了,就把他删去,答案为1但且仅当不存在这样被删去的会导致错误的点,边权为零的

用并查集维护连通块

点击查看代码
#include<bits/stdc++.h>
const int maxn=3e5+10;
using namespace std;
int n,head[maxn],nxt[maxn<<1],to[maxn<<1],tot,p[maxn],fa[maxn],size[maxn],in[maxn];
int x[maxn],y[maxn],z[maxn],cnt,sum,son[maxn],ans[maxn];
bool vis[maxn];
set<int>q[maxn]; 
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}

void del(int x)
{	
	if(q[x].size()<=2&&!size[x])
	{
		sum--;int temp=0;
		for(auto i:q[x]) son[++temp]=i;
		q[x].clear();
		for(int i=1;i<=temp;i++)
		{
			q[son[i]].erase(x);
			for(int j=i+1;j<=temp;j++)
			{
				q[son[i]].insert(son[j]);
				q[son[j]].insert(son[i]);	
			}
		}
		for(int i=1;i<=temp;i++) del(son[i]);
	}
}

int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<n;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		if(!c)
		{
			a=find(a),b=find(b);
			if(a>b) swap(a,b);
			fa[b]=a;
			continue;
		}
		x[++cnt]=a,y[cnt]=b;
	}
	for(int i=1;i<n;i++) q[find(x[i])].insert(find(y[i])),q[find(y[i])].insert(find(x[i]));
	for(int i=1;i<=n;i++)
	{
		cin>>p[i];
		p[i]=find(p[i]);
		size[p[i]]++;
	}
	for(int i=n;i>=1;i--)
	{
		ans[i]=!sum;
		size[p[i]]--;
		if(!size[p[i]]) sum++,del(p[i]);
	}
	for(int i=1;i<=n;i++) cout<<ans[i];

	return 0;
}
/*
10
5 9 0
6 9 6
7 6 9
1 7 5
10 1 2
8 10 0
4 10 5
3 4 9
2 5 4
4 5 3 7 8 9 6 2 1 10

5
1 2 3
1 5 0
2 3 2
2 4 3
1 3 4 2 5
*/
posted @ 2024-09-29 11:23  _君の名は  阅读(11)  评论(0编辑  收藏  举报