csp模拟赛 6 9.28

0+40+10+0

一言以蔽之 曰 “一上午白干”

T1 一般图最小匹配

首先,对答案有贡献的点对一定在排序后的位于相邻位置

所以排序后取出所有 \(a_{i+1}-a_{i}\)

但不能像Kruskal一样每次取最小,因为其只需要考虑连通性,不涉及其它限制。

所以用dp或者可反悔贪心取最优解

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int a[50005];
int dp[5005][5005];
signed main()
{
	freopen("match.in","r",stdin);
 	 freopen("match.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	memset(dp,0x3f,sizeof(dp));
	for(int i=0;i<=n;i++) dp[i][0]=0;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=min(i/2+1,m);j++)
		{
			dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+a[i]-a[i-1]);
		}
	}
	cout<<dp[n][m];
}

T2 重定向

从前向后扫描

对于分别考虑 \(a_{i}\)\(a_{i+1}\) 是否选到 0,共四种情况。

用set维护出每个为 0 的位置可以填下的数

另外, 对于 一种情况 \(a_{i}=0\) 并且存在\(j>i\)并且\(a_{j}\)小于其可选的最小至,此时直接删除\(j\)

点击查看代码

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> ma;
int a[500005];
bool f[500005];
set<int >stk,sty;
int n;
int main()
{
	freopen("repeat.in","r",stdin);
	freopen("repeat.out","w",stdout);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;
		memset(f,0,sizeof(f));
		stk.clear();
		sty.clear();
		ma.clear();
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			if(a[i]) f[a[i]]=1,ma[a[i]]=i;
		}
		for(int i=1;i<=n;i++)
		{
			if(!f[i]) stk.insert(i);
			else sty.insert(i);
		}
		int wei=0;
		for(int i=1;i<=n;i++)
		{
			if(a[i]) sty.erase(a[i]);
			if(a[i]&&a[i+1])
			{
				if(a[i]>a[i+1])
				{
					stk.insert(a[i]);
					wei=i;
					break;
				} 
			}
			if(a[i+1]==0&&a[i])
			{
				int x=*stk.begin();
				if(x<a[i])
				{
					stk.insert(a[i]);
					wei=i;
					break;
				}
			 }
			if(a[i]==0)
			{
				int x=*stk.begin();
				int y=*sty.begin();
				if(y<x)
				{
					a[i]=y;
					sty.erase(y);
					wei=ma[y];

					//cout<<"__";
					break;
				}
				else
				{
					a[i]=x;
					stk.erase(x);
				} 
			}

		}
		if(wei==0) wei=n;
		for(int i=1;i<=n;i++) 
		{
			if(wei==i) continue;
			if(a[i]==0)
			{
				int x=*stk.begin();
				//int y=*sty.begin();
				a[i]=x;
				stk.erase(x);
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(wei==i) continue;
			//tot++;
			cout<<a[i]<<' ';
		}
		cout<<'\n';
	}	
}

T3 斯坦纳树

对于当前点集,当且仅当其在原树上形成的虚树存在虚点时答案为 0;

将用边权为0的边相连的点 ,合并为一个大点,只要大点内有一个点存在,即表示该大点存在;

  • 可正徐维护,依次加点,将已有点集按\(dfs\) 序排序 ,将新增节点填入,若其与左右两个节点分别形成的lca都位于已有点集内,则无新增虚点

  • 也可倒叙删点,对要删除点,若当前相连的边数大于3,则设为虚点;若等于2,则删除,并将与其相连的两个点连边,保持连通性;若等于1 直接删除; 对于每次删除要递归处理

点击查看代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	int f,to,next,w;
}ee[600005],e[600005];
int head[300005],cnt1,cnt;
bool del[300005],xvd[300005];
int fa[300005],siz[300005],in[300005],p[300005];
bool ans[300005];
int n,xv;
void add(int f,int t,int w)
{
	e[++cnt].to=t;
	e[cnt].f=f;
	e[cnt].w=w;
	e[cnt].next=head[f];
	head[f]=cnt;
}
int find(int x)
{
	if(fa[x]!=x) fa[x]=find(fa[x]);
	return fa[x];
}
void merge(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx==fy) return;
	fa[fx]=fy;
	siz[fy]+=siz[fx];
}
void delet(int x)
{
	del[x]=1;
	if(in[x]==2)
	{
	int num1=0,num2=0;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(!del[y]&&num1==0) num1=y; 
		else if(!del[y]&&num1) num2=y;
	}
	add(num1,num2,1);
	add(num2,num1,1);
	in[num1]++;
	in[num2]++;
	}
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(!del[y])
		{
			in[y]--;
			if(xvd[y]&&in[y]==2)
			{
				xvd[y]=0;
				del[y]=1;
				xv--;
				delet(y);
			}
		}
	}
}
int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);	
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
		siz[i]=1;
	}
	for(int i=1;i<n;i++)
	{
		int x,y,w;
		cin>>x>>y>>w;
		if(w==0) merge(x,y);
		else 
		{
			ee[++cnt1].f=x;
			ee[cnt1].to=y;
			ee[cnt1].w=w;
		}
	}
	for(int i=1;i<=cnt1;i++)
	{
		int lx=find(ee[i].f),ly=find(ee[i].to);
		in[lx]++,in[ly]++;
		add(lx,ly,e[i].w);
		add(ly,lx,e[i].w);
	}
	for(int i=1;i<=n;i++) cin>>p[i];
	for(int i=n;i>=1;i--)
	{
		ans[i]=(xv==0);
		int lx=find(p[i]);
		siz[lx]--;
		if(siz[lx]) continue;
		if(in[lx]>=3) xvd[lx]=1,xv++;
		else 
		{
			del[lx]=1;
			delet(lx);
		} 
	}
	for(int i=1;i<=n;i++) cout<<ans[i];
}

T4

不会


网络流
感觉 P2754在暗示什么 打了四遍都在保存前,电脑死机了

posted @ 2024-09-28 21:41  程立雪  阅读(36)  评论(2编辑  收藏  举报