题意:n个核电站,m条电缆,每个核电站有一个耗电量,电缆传输功耗为两个核电站耗电量之间的异或值。其中有一个核电站为耗电量为-1,表示我们可改变该核电站的耗电量,求总最低传输功耗,并求在此基础上的最低总耗电量?

思路:我可以改变的只有一个核电站,所以我能决定的传输功耗为与该核电站相连的电缆,所以将于该核电站相连电缆所连的核电站提出来,用数组保存,又由于电缆传输功耗为两个核电站耗电量之间的异或值,所以从位考虑,如果该位为1则所连的核电站中该位为0的会产生等价于位权值的传输功耗,所以当所连的核电站中该位为0小于为1的时候该位为1。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 1000000007

using namespace std;

inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

ll w[1005], a[10005];

int main()
{
    int n, m, s, ji=0;
    scanf("%d%d",&n,&m);
    ll sum=0, sumw=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&w[i]);
        if(w[i]==-1)
        {
            s=i;
        }
        else
        {
            sum=sum+w[i];
        }
    }
    for(int i=0;i<m;i++)
    {
        int u, v;
        scanf("%d%d",&u,&v);
        if(u!=s&&v!=s)
        {
            sumw+=(w[u]^w[v]);
        }
        else if(u==s)
        {
            a[ji++]=v;
        }
        else
        {
            a[ji++]=u;
        }
    }
    ll z=0;
    for(int i=0;i<31;i++)
    {
        int p=0;
        for(int j=0;j<ji;j++)
        {
            if((w[a[j]]>>i)&1)
            {
                p++;
            }
        }
        if(p>ji-p)
        {
            z=z+(1LL<<i);
        }
    }
    sum+=z;
    for(int i=0;i<ji;i++)
    {
        sumw+=(w[a[i]]^z);
    }
    printf("%lld\n",sumw);
    printf("%lld\n",sum);
    return 0;
}