题意: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; }