河南萌新2024第四场

C 岗位分配

题目大意:

有n个岗位,m位志愿者,每个岗位至少需要a个志愿者,并且可以有志愿者可以空闲下来作预备,给出可能的分配情况总数

思路:

首先将每个岗位分配好至少需要的志愿者,再将剩下的人进行分配,那就满足 球同盒不同模型(允许空盒),可用隔板法进行分配,需要额外开设一个空闲岗位用来预备,那么按照4个人去4个岗位,那么为c 7 3 ,具体操作可看数论模板中发布的隔板法问题,递归求组合数

Solved:

	int n,m;cin>>n>>m;
	int q=n;
	while(q--){
		int x;cin>>x;
		m-=x;
	}
	for(int i=0;i<N;i++){
		for(int j=0;j<=i;j++){
			if(j==0) C[i][j]=1;
			else C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
		}
	}  
	cout<<(C[n+m][n])%mod<<endl;

I 马拉松

题目大意:

有n个城市,编号1-n,有n-1条双向道路连接这些城市,每天都会在一对城市 (u ,v)之间举办一次马拉松,该国家有两个城市 x 和 y,当小明经过 x 城市后又跑到 y 城市,那么该城市的警察就会阻止小明继续参加比赛。想知道有多少个马拉松在他参加时会被阻止

思路:

该题目有点像 算法进阶指南中楼兰图腾的变形,在楼兰图腾中求的是在一个序列中先升后降 和先降后升的图案总数,如果是先升后降,需要遍历每个数字左边所有比该数小的数字,右边比该数小的数字,相乘就是该数字构成的图案总数,

该题目中只需要在图中求得 与x城市直连但到达不了y城市的数量(楼兰图腾中数字左边所有比该数小的数字数量) * 与y城市直连但到达不了x城市的数量(楼兰图腾中数字右边所有比该数小的数字数量),相乘就是在所有路径中通过x城市到达y 城市的所有路径

在求法方面比较特殊,我们只需要通过x城市bfs遍历所有能够到达的城市,并将其独特标记+1直到找到y城市,停止

通过y城市bfs所有能够到达的城市,并将其独特标记+2

这样标记为3的城市即为两城市之间的所有城市

标记为1的城市就是与x城市直连但到达不了y城市的城市

标记为2的城市就是与y城市直连但到达不了x城市的城市

数据范围3e5,不可用数组模拟邻接表存图,卡内存,需要vector存图

Solved:

int st[N], cnt[N];//st标记城市是否来过,cnt标记与x,y分别直连的城市
void bfs(int x, int y, int num) {
    memset(st, 0, sizeof(st));
    queue<int> q;
 
    q.push(x);
 
    while (!q.empty()) {
        int t = q.front();
        q.pop();
 
        if (st[t] != 0 || t == y)
            continue;
 
        st[t] = 1;
        cnt[t] += num;
        for (auto ee : e[t]) {
            q.push(ee);
        }
    }
}
vector<int> e[N];//邻接表
void solve() {
    cin >> n >> x >> y;
    for (int i = 1; i <= n - 1; i++) {
        int xx, yy;
        cin >> xx >> yy;
        //存图
        e[xx].push_back(yy);
        e[yy].push_back(xx);
    }
    //遍历城市并标记
    bfs(x, y, 1);
    bfs(y, x, 2);
 
    int cnt1 = 0, cnt2 = 0;
    //遍历数量
    for (int i = 1; i <= n; i++) {
        if (cnt[i] == 1)
            cnt1++;
        if (cnt[i] == 2)
            cnt2++;
    }
    cout << cnt1 *cnt2 << endl;
}

你可能感兴趣的:(算法,数据结构)