七石二是南黑蜗牛寺的新住寺神。她的第一份工作是:在x县有n个新城市,城市编号从1到n。城市i位于神社以北1公里,神社以东y公里。(æi, yi) = (æj, Vj)是可能的,即使i # j。七石市必须为每个城市提供电力,方法是在每个城市建立一个发电站,或者在这个城市和另一个已有电力的城市之间建立连接。所以,如果一个城市有发电站,或者它通过直接连接或通过连接链连接到一个有电的城市,这个城市就有电。在城市i建造一个发电站将花费c日元;在i市和j市之间进行连接将花费k + k日元每公里用于连接的电线。然而,导线只能向基本方向(北、南、东、西)移动。电线可以互相交叉。每根导线的两端都必须位于某些城市。如果用一根导线连接城市i和城市j,导线将通过从城市i到城市j的任何最短路径。因此,如果连接城市耶内和城市j,导线的长度为æ æjl + lyi - yl km。Shichikuji想尽可能少花钱做这份工作,因为在她看来,世界上除了钱就没有其他东西了。然而,她在五年级的时候就去世了,所以她不够聪明。因此,新的常驻神需要你的帮助。因此,你必须向七城提供以下信息:向所有城市提供电力所需的最低日元金额,将在哪些城市建造发电站,以及将建立的连接。如果有多种方式选择城市和连接,以获得最低价的建设,然后打印其中任何一个。输入第一行输入包含一个整数n(1≤n≤2000)——城市数量。然后,有n行。第i行包含两个用空格分隔的整数x;(1 <x < 10°)和y;(1 < y;< 10) -第i个城市的坐标。下一行包含n个用空格分隔的整数c1, C2,..,Cn (1 < c < 10°)-在第i个城市建造一座发电站的费用。最后一行包含n个用空格分隔的整数k1, k2, .., kn (1 < ki≤10°)。
输出在第一行打印一个整数,表示所需日元的最小金额。然后,打印一个整数v-要建造的发电站的数量。接下来,打印v个用空格分隔的整数,表示将要建造电站的城市的指数。每个数字应该在1到n之间,并且所有数字都应该是成对不同的。你可以按任意顺序打印这些数字。在此之后,打印一个整数e-要建立的连接数。最后,打印e对整数a和b (1 < a,b≤n, a b),表示将建立城市a和城市b之间的连接。每个无序城市对最多应该被包含一次(对于每个(a, b)不应该有更多的(a, b)或(b, a)对)。您可以以任意顺序打印这些对。如果有多种方式选择城市和连接,以获得最低价的建设,然后打印其中任何一个。
Examples
input
Copy
3 2 3 1 1 3 2 3 2 3 3 2 3
output
Copy
8 3 1 2 3 0
input
Copy
3 2 1 1 2 3 3 23 2 23 3 2 3
output
Copy
27 1 2 2 1 2 2 3
题解:
把每个城市,连一个到超级源点的边,边权为c,接着每两个点连接,加权
跑最小生成树板子即可
连一个到超级源点的边其实就是判断,到底是连边还是在这个点建电站,为什么可行,因为这样的话,在排序时,就把最优情况放在前面了,
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
struct node
{
int x,y,c,k;
}a[2005];
struct nod
{
int fa,ne,w;
}p[4000040];
int cnt = 0;
int sum = 0;
vector<int> ans;
vector<PII> res;
int f[2005];
int find(int x)
{
if(f[x] == x)
return x;
return f[x] = find(f[x]);
}
bool cmp(nod a,nod b)
{
return a.w < b.w;
}
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> a[i].x >> a[i].y;
}
for(int i = 1;i <= n;i++)
f[i] = i;
for(int i = 1;i <= n;i++)
{
cin >> a[i].c;
p[++cnt].fa = 0;
p[cnt].ne = i;
p[cnt].w = a[i].c;
}
for(int i = 1;i <= n;i++)
{
cin >> a[i].k;
}
for(int i = 1;i <= n;i++)
{
for(int j = i + 1;j <= n;j++)
{
p[++cnt].fa = i;
p[cnt].ne = j;
p[cnt].w = (abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y))*(a[i].k + a[j].k);
}
}
sort(p + 1,p +1 + cnt,cmp);
int s = 0;
for(int i = 1;i <= cnt;i++)
{
int x = find(p[i].fa);
int y = find(p[i].ne);
if(x == y)
{
continue;
}
if(p[i].fa == 0)
{
ans.push_back(p[i].ne);
}
else
{
res.push_back({p[i].fa,p[i].ne});
}
f[x] = y;
sum += p[i].w;
s++;
if(s == n)
break;
}
cout << sum <<"\n";
cout << ans.size() <<"\n";
for(auto i:ans)
cout <<i << ' ';
cout <<"\n";
cout << res.size() <<"\n";
for(auto t:res)
{
cout <<t.first <<" "<<t.second <<"\n";
}
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}