题目:https://www.hackerrank.com/challenges/torque-and-development/problem
题意:q组test,n个城市,m条损坏的路,在每个城市修图书馆代价为clib,修每条路为croad,求所有城市都能接触到图书馆的最小花费
思路:首先情况有两种,每个L点连通图修一个图书馆、L-1路,每个L点连通图修L个图书馆,所以如果croad >= clib的话,直接建n个图书馆就行了;找连通图的L-1路用DFS或者并查集
ps:注意描述的croad , clib顺序和输入的不一样,害得我多写了个并查集才发现,哭
1.DFS直接找每个连通分量的点数就行了,贴个官方题解的代码:
#include <bits/stdc++.h>
using namespace std;
vector<int> adj[100005];
bool visited[100005];
long nodes;
void DFS(int n)
{
nodes++;
visited[n] = true;
for(vector<int>::iterator i = adj[n].begin(); i != adj[n].end() ; i++)
{
if(!visited[*i])
DFS(*i);
}
}
int main()
{
int T;
cin >> T;
while(T--)
{
int N,M,a,b;
long X,Y;
cin >> N >> M >> X >> Y;
for(int i = 0 ; i < M ; i++)
{
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
long cost=0;
for(int i = 1 ; i <= N ; i++)
{
if(!visited[i])
{
nodes = 0;
DFS(i);
cost = cost + X;
if(X > Y)
cost = cost + (Y*(nodes-1));
else
cost = cost + (X*(nodes-1));
}
}
cout << cost << endl;
for(int i=0 ; i<=N ; i++)
{
adj[i].clear();
visited[i] = false;
}
}
return 0;
}
2.并查集代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 100005;
int f[N];
void init()
{
for(int i = 1;i < N;i++)
f[i] = i;
}
int getf(int x)
{
return x == f[x] ? x : f[x] = getf(f[x]);
}
void merge(int u,int v)
{
int fu = getf(u);
int fv = getf(v);
if(fu != fv)
f[fv] = fu;
}
int main()
{
int q,n,m,croad,clib,u,v;
scanf("%d",&q);
while(q--)
{
init();
scanf("%d%d%d%d",&n,&m,&clib,&croad);
while(m--)
{
scanf("%d%d",&u,&v);
merge(u,v);
}
if(croad >= clib){
printf("%lld\n",1ll*clib*n);
continue;
}
ll ans = 0;
for(int i = 1;i <= n;i++)
if(f[i] == i)
ans += clib;//建图书馆
else
ans += croad;
printf("%lld\n",ans);
}
return 0;
}