列表

详情


NC230374. 突破模式

描述

贪玩的lyw最近迷上了BattlefieldⅤ的突破模式。他发现有时候指导队友去正确的地区参与战斗会对整场战役发挥不小的作用。

lyw所在的游戏地图一共有n个节点,编号为1n,它们分别位于m个大战区之内。每个大战区里的道路和节点都形成一棵有根树,其中根节点被称为决战区域(该根节点没有指向任何一个节点的道路),满足所有大战区的节点数之和为n

当前i号节点有a_i个士兵正在战斗,而当位于该节点的人数大于等于b_i(b_i>a_i)时,这群士兵就将突破这个节点,保持现有的人数,沿着有向的道路进入下一个节点;当一群士兵突破了一个大战区的决战区域时,他们将驻守在这里。

当所有大战区的决战区域都被突破时,lyw一方就将赢得战役。

lyw可以靠自己的努力凭空变出任意人数的士兵。他想知道,如果他只在每个大战区的一个节点增派士兵,最少增派多少士兵才能让他们一路摧枯拉朽打赢整场战役?

输入描述

第一行两个正整数
接下来的n行,每行两个正整数
接下来的n-m行,每行两个正整数,表示地图中有一条由u通向v的有向道路。

输出描述

输出一个整数,表示最少需要派遣的士兵数量。

示例1

输入:

3 1
0 1
0 2
0 2
2 1
3 1

输出:

1

示例2

输入:

7 2
10 100
20 30
40 55
0 11
10 99
10 11
0 1
2 1
3 1
5 4
7 6
6 4

输出:

51

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 48ms, 内存消耗: 5848K, 提交时间: 2022-11-20 13:32:12

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7;
vector<vector<int>> adj(N);
int indeg[N],f[N],a[N],b[N],root[N],tot;
int dfs(int cur,int par)
{
    int ans = 0x7f7f7f7f;
    f[cur] = b[cur] - a[cur] + max(f[par] - b[cur],0);
    ans = min(f[cur],ans);
    for(int u : adj[cur])
        ans = min( dfs(u,cur),ans );
    return ans;

}
void solve()
{
    int n,m,sum = 0;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d %d",a + i,b + i);
    for(int i=0;i<n-m;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        adj[v].push_back(u);
        indeg[u]++;
    }
    for(int i=1;i<=n;i++)
        if (!indeg[i])
            root[++tot] = i;
    for(int i = 1;i<=tot;i++)
        sum += dfs(root[i],0);
    printf("%d\n",sum);
}

int main()
{
    solve();
}

Python3 解法, 执行用时: 733ms, 内存消耗: 46828K, 提交时间: 2022-06-20 10:00:42

n,m=map(int,input().split())
team=[]
road={}
a=set()
b=set(x for x in range(n))
for _ in range(n):
    team.append([int(x) for x in input().split()])
for _ in range(n-m):
    x ,y =[int(x)-1 for x in input().split()]
    if y not in road:
        road[y] = [x]
    else:
        road[y].append(x)
    a.add(x) #左边都是非决战区
varea = list(b-a)  #决战区
soldier=0
res=[0]
def dfs(x,y): #节点,到达该节点需要多少人
    y = max(y,team[x][1]) - team[x][0]
    res[0] =  min(y,res[0])
    if x not in road:
        return
    for r in road[x]:
        dfs(r,y)
    return
for x in varea:
    res[0] = team[x][1] -  team[x][0]
    tmp = res[0]
    dfs(x,tmp)
    soldier  = soldier + res[0]
print(soldier)

C++ 解法, 执行用时: 104ms, 内存消耗: 5624K, 提交时间: 2021-11-23 15:00:26

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int a[N],b[N],f[N],in[N];
vector<int> g[N];
int n,m;
int ans , res ;
void dfs(int u,int need){
	f[u] = max(f[u],f[u]+need-b[u]);
	res = min(res,f[u]);
	for(auto v : g[u]){
		//vis[v]=1;
		dfs(v,f[u]);
	}
}
int main() {
	cin >> n >> m;
	for(int i=1; i<=n; i++) {
		cin >> a[i] >> b[i];
		f[i]= b[i]-a[i];
	}
	for(int i=1;i<=n-m;i++){
		int u,v;
		cin >> u >> v;
		g[v].push_back(u);
		in[u]++;
	}
	for(int i=1;i<=n;i++){
		if(!in[i]){
			//vis[i]=1;
			res = 0x3f3f3f3f;
			dfs(i,0);
			ans+=res;
		}
	}
	cout << ans << endl;
	return 0;
}

上一题