10-24——10-31ACM笔记

1.树的计数
我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的 DFS 序以及 BFS 序。两棵不同的树的 DFS 序有可能相同,并且它们的 BFS 序也有可能相同,例如下面两棵树的 DFS 序都是 1 2 4 5 3,BFS 序都是 1 2 3 4 5。

题意十分简明,给定 dfs 序与 bfs 序,求这棵树树高的平均值。
首先从 bfs 入手,因为 bfs 序可以的一段可以对应树的一层。
记 dfndfn 为 ii 在 dfs 序中的位置,
记 bfnbfn 为 ii 在 bfs 序中的位置。
那么对于每一个点 ii,接下来考虑这三种情况:
只能分成 22 层:贡献为 11
1,21,2 层都可以:贡献为 0.50.5
只能分成 11 层:贡献为 00

#include <bits/stdc++.h>
using namespace std;
int n;
int d[300001];
int bfn[300001];
int dfn[300001];
int revd[300001];
int revb[300001];
double ans;
int main(){
	scanf("%d", &n);
	ans = 2;
	++ d[1];
	-- d[2];
    for (int i = 1; i <= n; ++ i) {
		scanf("%d", dfn + i);
		revd[dfn[i]] = i;
	}
    for (int i = 1; i <= n; ++ i) {
		scanf("%d", bfn + i);
		revb[bfn[i]] = i;
	}
    for (int i = 1; i <= n; ++ i) {
		dfn[i] = revb[dfn[i]];
		bfn[i] = revd[bfn[i]];
	}
    for (int i = 1; i < n; ++ i)
		if(bfn[i] > bfn[i + 1])
			++ d[i], -- d[i + 1], ++ ans;
    for (int i = 1; i < n; ++ i)
		if(dfn[i] + 1 < dfn[i + 1])
			++ d[dfn[i]], -- d[dfn[i + 1]];
	int w = 0;
    for (int i = 1; i < n; ++ i) {
		w += d[i];
		if(!w) ans += 0.5;
	}
	printf("%.3f", ans);
}

2.最短路计数
给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N。问从顶点11开始,到其他每个点的最短路有几条。

因为所有的边权都为1,所以一个点的最短路就相当于是它在BFS搜索树中的深度。
一个点最短路一定经过了一个层数比它少一的结点(否则不是最短路)。
所以用每个相邻且层数比当前结点层数少一的点更新当前点的路径跳数即可。

#include<bits/stdc++.h>
using namespace std;

const int maxn=1000000+1,maxm=2000000+1,INF=0x7f7f7f7f,MOD=100003;
vector<int>G[maxn];int dep[maxn];bool vis[maxn];int cnt[maxn];

int main(){
    int N,M;scanf("%d%d",&N,&M);
    for(int i=1;i<=M;i++){
        int x,y;scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    queue<int>Q;dep[1]=0;vis[1]=1;Q.push(1);cnt[1]=1;
    while(!Q.empty()){
        int x=Q.front();Q.pop();
        for(int i=0;i<G[x].size();i++){
            int t=G[x][i];
            if(!vis[t]){vis[t]=1;dep[t]=dep[x]+1;Q.push(t);}
            if(dep[t]==dep[x]+1){cnt[t]=(cnt[t]+cnt[x])%MOD;}
        }
    }
    for(int i=1;i<=N;i++){
        printf("%d\n",cnt[i]);
    }
    return 0;

DIV2:
A. Luntik and Concerts
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Luntik has decided to try singing. He has a one-minute songs, b two-minute songs and c three-minute songs. He wants to distribute all songs into two concerts such that every song should be included to exactly one concert.

He wants to make the absolute difference of durations of the concerts as small as possible. The duration of the concert is the sum of durations of all songs in that concert.

Please help Luntik and find the minimal possible difference in minutes between the concerts durations.

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    int t;  cin>>t;
    while(t--){
        int a,b,c;  cin>>a>>b>>c;
        cout<<(a+c)%2<<endl;
    }
    return 0;
}

很简单,但最开始用的办法太复杂,还tl了。浪费了时间。
B. Luntik and Subsequences
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Luntik came out for a morning stroll and found an array a of length n. He calculated the sum s of the elements of the array (s=∑ni=1ai). Luntik calls a subsequence of the array a nearly full if the sum of the numbers in that subsequence is equal to s−1.

Luntik really wants to know the number of nearly full subsequences of the array a. But he needs to come home so he asks you to solve that problem!

A sequence x is a subsequence of a sequence y if x can be obtained from y by deletion of several (possibly, zero or all) elements.

```cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
	
	int t,n;
	long long a;
	cin >> t;
	while (t--) {
		long long c1 = 0;
		long long c2 = 0;
		cin >> n;
		for (int i = 0;i < n;i++) {
			cin >> a;
			if (a == 1) {
				c1++;
			} else if (a == 0) {
				c2++;
			}
		}
		long long ans = pow(2,c2)*c1;
		cout << ans << endl;
	}
	return 0;
}
 

``能影响结果的就是0和1的数量,转化成组合,2的n次方乘以1的个数就是结果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值