列表

详情


NC229894. 牛牛选路径

描述

牛牛有一张无向连通图,图上有 n 个点和 m 条边,每个点有一个权值a_i

现在牛牛想选出最少的路径(一条路径可以重复覆盖同一条边),使得每条边被覆盖奇数次,并且使这些路径权值和最小。

一条路径的权值定义为:路径两端节点的点权之积。

他现在想知道最小的权值和。

输入描述

第一行,输入两个正整数 n,m,表示图的规格。

第二行,输入 n 个正整数 a_i,表示点 i 的权值。

接下来 m 行,每行两个正整数 u,v,表示 uv 之间连有一条边。

对于  的数据, ,且数据保证是一个连通图。

输出描述

一个正整数,表示最小的路径权值和。(答案对998244353取模)

示例1

输入:

5 7
83 49 41 75 92 
1 5
1 3
5 4
1 2
2 5
4 3
1 3

输出:

3772

说明:

一种可行的办法,一条路径为3->1->5->2->1->3->4->5,所以路径的权值是41*92

原站题解

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

pypy3 解法, 执行用时: 1749ms, 内存消耗: 35752K, 提交时间: 2021-12-13 11:00:33

n, m = map(int, input().split())

a = list(map(int, input().split()))

in_edge = [0 for i in range(n)]
for i in range(m):
  u, v = map(int, input().split())
  u -= 1
  v -= 1
  in_edge[u] += 1
  in_edge[v] += 1

odd_vertex = []

for i in range(n):
  if in_edge[i] & 1:
    odd_vertex.append(i)

mod = 998244353

if len(odd_vertex) == 0:
  a.sort()
  print(a[0] * a[0] % mod)
else:
  tmp = []
  for vertex in odd_vertex:
    tmp.append(a[vertex])
  tmp.sort()
  k = len(tmp)
  ans = 0
  for i in range(k // 2):
    ans += tmp[i] * tmp[k - i - 1]
    ans %= mod
  print(ans)    

C++ 解法, 执行用时: 154ms, 内存消耗: 1280K, 提交时间: 2021-12-10 20:05:23

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

int n,m,a[100005],b[100005],d[100005],bn; 

int main(){
	scanf("%d%d",&n,&m);
	int mina=10000;
	for (int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		mina=min(mina,a[i]);
	}
	for (int i=1;i<=m;i++){
		int x,y;scanf("%d%d",&x,&y);
		d[x]^=1;d[y]^=1;
	}
	for (int i=1;i<=n;i++) if (d[i]) b[++bn]=a[i];
	sort(b+1,b+bn+1);
	ll ans=0;
	for (int i=1;i<=bn/2;i++) ans+=1ll*b[i]*b[bn-i+1];
	if (!bn) ans=mina*mina;
	cout<<ans;
}

上一题