牛牛選路徑(牛客)
阿新 • • 發佈:2021-12-15
感覺很像小時候玩的一個遊戲《一筆成畫》
保證圖連通,每條邊都經過奇數次,等價於每條邊只經過一次
對於重邊可以不考慮,1->3,3->1,再走回來就行了
發現路徑是什麼樣的不重要,重要的是起點和終點
發現起點和終點的度數一定是奇數
起點最後會引出一條出邊
終點最後會收回一條入邊
且起點和終點可以互換
所以預處理每個點的度數,判斷是否為奇數
特別的,如果所有的度數都為偶數,則構成一個環,只需要找到點權最小的即可
否則,起點和終點一定成雙成對,有多少對起終點就有多少條路徑
統計答案時:
設a<b<c<d
很容易證明ad+bc<ab+cd
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string> #include<string.h> #include<map> #include<set> #include<queue> #include<stack> #include<iomanip> #include<bitset> #include<climits> #ifdef _MSC_VER # include <intrin.h> # define __builtin_popcount __popcnt # define __lg log2 #endif #define N 100010 #define M 200010 #define INF 0x3f3f3f3f3f3f3f3f #define ll long long #define mod 998244353 using namespace std; ll n, m, a[N], d[N],s[N],cnt,ans; bool cmp(ll x, ll y) { return a[x] < a[y]; } int main() { scanf("%lld%lld", &n, &m); for (ll i = 1; i <= n; ++i) scanf("%lld", &a[i]); for (ll i = 1; i <= m; ++i) { ll u, v; scanf("%lld%lld", &u, &v); d[u]^=1; d[v]^=1; } for (ll i = 1; i <= n; ++i) if (d[i]) s[++cnt] = i; if (!cnt) { ll mi = INF; for (ll i = 1; i <= n; ++i) mi = min(mi, a[i]); printf("%lld\n", mi * mi % mod); } else { sort(s + 1, s + 1 + cnt, cmp); for (ll i = 1; i <= cnt / 2; ++i) ans = (ans + a[s[i]] * a[s[cnt - i + 1]] % mod) % mod; printf("%lld\n", ans); } return 0; }