题意: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;
}
京公网安备 11010502036488号