"蔚来杯"2022牛客暑期多校训练营5

A Don't Starve

巧妙在于拓扑排序 为啥要开滚动数组 因为对于长度相同的边 我们只能选择一条 而这些边属于同一个状态的 为了防止更新的时候对同状态的点造成影响

#include<bits/stdc++.h>
using namespace std;
int i,j,k,l,n,m,f[2005],g[2005];
struct op
{
	int x,y;
}s[100001];
struct ex
{
	int a,b;
	long long len;
}w[4000005];
bool cmp(ex x,ex y)
{
	return x.len<y.len;
}
int main()
{
	cin>>n;
	for (i=1;i<=n;i++) 
	{
		cin>>s[i].x>>s[i].y;
		w[++m].a=i;w[m].b=0;w[m].len=s[i].x*s[i].x+s[i].y*s[i].y;
	}
	for (i=1;i<=n;i++)
	  for (j=1;j<=n;j++)
		if (i!=j){ 
		    w[++m].a=i;w[m].b=j;
		    w[m].len=(s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y);
	    }
	sort(w+1,w+m+1,cmp);
	for (i=1;i<=m;i=j)
	{
		j=i;
		while (j<=m&&w[i].len==w[j].len) j++;
		for (k=i;k<j;k++) f[w[k].b]=max(g[w[k].a]+1,f[w[k].b]);
		for (k=i;k<j;k++) g[w[k].b]=max(g[w[k].b],f[w[k].b]);
	}
	cout<<g[0];
}

D Birds in the tree

如果当前点的颜色和当前考虑的颜色相同 则当前点也可以作为根节点度数为1

如果不相同 那么当前点作为根节点一定度数不能为1 所以就要减去作为根节点度数为1的所有情况

总结一下:

求连通子图的方案数 可以考虑分别以各个点为根节点 这样所有的连通子图就能考虑到了

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=3e5+5;
const int mod=1e9+7;
ll dp[maxn][2],ans;
int a[maxn];
vector<int>Q[maxn];
int n;
ll dfs(int u,int fa,int now){
	ll mul=1,sum=0;
	for(int i=0;i<Q[u].size();i++){
		int to=Q[u][i];
		if(to==fa)continue;
		dfs(to,u,now);
		mul=mul*(dp[to][now]+1)%mod;
		sum=(sum+dp[to][now])%mod;
	}
	dp[u][now]=(mul-1+(a[u]==now)+mod)%mod;
	if(now==a[u])
	ans=(ans+dp[u][now])%mod;
	else 
	ans=(ans+dp[u][now]-sum+mod)%mod;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)scanf("%1d",&a[i]);
    for(int i=1,u,v;i<n;i++){
    	scanf("%d%d",&u,&v);
    	Q[u].push_back(v);
    	Q[v].push_back(u);
	}
	dfs(1,1,1);
	dfs(1,1,0);
	cout<<ans<<endl;
	return 0;
}

posted @ 2022-09-07 15:47  wzx_believer  阅读(12)  评论(0编辑  收藏  举报