#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <math.h>
#define eps 1e-14
#define pi acos(-1)
#define ll long long
#define RD T*(rand()*2-RAND_MAX)
#define Drand (long double)rand()/RAND_MAX
#define LINF 0x7f7f7f7f7f7f7f7f
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=2e5+100;
const long long mod=1e9+7;
ll MOD(ll a,ll m){return a>m?a%m+m:a;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int pow_mod(int a, int n, int m){if(n == 0) return 1;int x = pow_mod(a, n/2, m);long long ans = (long long)x * x % m;if(n % 2 == 1) ans = ans *a % m;return (int)ans;}
struct nn
{
ll x,y;
nn(){}
nn(ll x,ll y):x(x),y(y){}
}ct[2005];
struct heap
{
int v;
ll w;
heap(){}
heap(int v,ll w):v(v),w(w){}
bool operator < (const heap & p)const
{
return w > p.w;
}
};
set<int>res2[2005];
vector<int>res1;
int n;
int path[2005];
ll c[2005],k[2005],l[2005][2005],dis[2005],vis[2005];
ll prim()
{
memset(dis,LINF, sizeof(dis));
priority_queue<heap>q;
q.push(heap(n+1,0));
dis[n+1]=0;
while(!q.empty()){
heap now=q.top();
q.pop();
int u=now.v;
ll w=now.w;
if(vis[u]==1)continue;
vis[u]=1;
for(int i=1;i<=n;i++){
if(vis[i]==0 && dis[i]>l[i][u]){//vis[i]==0不可漏判,不懂
dis[i]=l[i][u];
q.push(heap(i,l[i][u]));
path[i]=u;
}
}
}
ll ans=0;
for(int i=1;i<=n+1;i++){
// cout<<"dis "<<dis[i]<<endl;
ans+=dis[i];
}
for(int i=1;i<=n;i++){
int x=i,y=path[i];
if(x==n+1 || y==n+1){
res1.push_back(min(x,y));
}
else{
if(x>y)swap(x,y);
res2[x].insert(y);
}
}
return ans;
}
int main()
{
// freopen("../in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll a,b;
scanf("%lld%lld",&a,&b);
ct[i].x=a;
ct[i].y=b;
}
for(int i=1;i<=n;i++){scanf("%lld",&c[i]);}
for(int i=1;i<=n;i++){scanf("%lld",&k[i]);}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
l[i][j]=(abs(ct[i].x-ct[j].x)+abs(ct[i].y-ct[j].y))*(k[i]+k[j]);
l[j][i]=l[i][j];
}
}
for(int i=1;i<=n+1;i++)l[i][i]=LINF;
for(int i=1;i<=n;i++)l[i][n+1]=c[i],l[n+1][i]=c[i];
printf("%lld\n",prim());
int len=res1.size();
printf("%d\n",len);
for(int i=0;i<len;i++){
printf("%d",res1[i]);
i==len-1 ? printf("\n") : printf(" ");
}
len=0;
for(int i=1;i<=n;i++){
len+=res2[i].size();
// cout<<i<<" "<<res2[i]
}
printf("%d\n",len);
for(int i=1;i<=n;i++){
int ed=res2[i].size();
for(auto it=res2[i].begin();it!=res2[i].end();it++){
printf("%d %d\n",i,*it);
}
}
return 0;
}
优先队列最小生成树prim
最新推荐文章于 2023-01-27 21:24:51 发布