思路

这题是Easy版本,只有一个发电站耗电量不确定,所以只需要统计与这个发电站直接相连的发电站的耗电量。

因为是要异或和最小,所以这里我统计了与未知发电站直接相连的发电站功耗的贡献,如果某一位1的个数大于0的个数那耗电量在这意味就是1。(异或让贡献尽可能小)

其他的直接暴力算就好,要注意电缆的消耗因为算了两次所以最后的答案要除2

代码

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
inline void write(__int128 x) { if (!x) { putchar('0'); return; } char F[50]; __int128 tmp = x > 0 ? x : -x; if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]); }
#define pb push_back
#define pll pair<ll,ll>
#define INF 0x3f3f3f3f
const int mod = 1e9+7;
const int maxn = 100005;
inline ll read(){
    ll s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}
ll w[505];
vector<int> q[505];
int num[35];
int main(){
    int n = read(),m = read();
    int st;
    for(int i = 1 ;i <= n ; ++i){
        w[i] = read();
        if(w[i] == -1) st = i;//记录未知功耗发电站位置
    }
    while(m--){
        int u = read(),v = read();//建图
        q[u].pb(v);
        q[v].pb(u);
    }
    for(int i = 0 ; i < q[st].size() ; ++i){//统计位置功耗发电站直接连接的数的贡献
        for(int j = 0 ; j < 32 ; ++j){
            num[j] += ((w[q[st][i]]>>j)&1);
        }
    }
    ll cnt = 0;
    for(int i = 31 ; i >= 0 ; --i){//计算位置功耗发电站的功耗
        cnt = cnt << 1;
        if(num[i] > q[st].size() - num[i]) cnt += 1;
    }
    w[st] = cnt;
    __int128 ans = 0;cnt = 0;
    for(int i = 1 ; i <= n ; ++i){
        cnt += w[i];//所有发电站功耗
        for(int j = 0 ; j < q[i].size() ; ++j){
            ans += w[i]^w[q[i][j]];//电缆功耗
        }
    }
    write(ans/2);putchar(10);
    cout<<cnt<<endl;
}