题目链接:搭配购买 - 洛谷
题面:
思路:刚开始我以为是有向图,洋洋洒洒敲了一长串的kosaraju算法,结果样例都过不了,后来看到了是无向图,那么并查集和强连通都可以解决,进行缩点操作,然后跑一遍01背包
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define ll long long
#define N 10005
vector<int> ve[N];
struct node{
int v, w;
}arr[N];
bool vis[N];
int f[N];
int dp[N];
vector<node> ans;
void dfs(int x, int y){
vis[x] = 1;
f[x] = y;
for(int i = 0; i < ve[x].size(); i++){
int to = ve[x][i];
if(vis[to] == 0){
dfs(to, y);
}
}
}
int main(){
ios::sync_with_stdio(false);
int n, m, w;
while(cin >> n >> m >> w){
ans.clear();
for(int i = 1; i <= n; i++){
cin >> arr[i].v >> arr[i].w;
ve[i].clear();
vis[i] = 0;
}
for(int i = 1; i <= m; i++){
int a, b;
cin >> a >> b;
ve[a].push_back(b);
ve[b].push_back(a);
}
for(int i = 1; i <= n; i++){
if(vis[i] == 0){
dfs(i, i);
}
}
for(int i = 1; i <= n; i++){
if(f[i] != i){
arr[f[i]].v += arr[i].v;
arr[f[i]].w += arr[i].w;
}
}
for(int i = 1; i <= n; i++){
if(f[i] == i){
ans.push_back(arr[i]);
}
}
memset(dp, 0, sizeof(dp));
for(int i = 0; i < ans.size(); i++){
for(int j = w; j >= ans[i].v; j--){
dp[j] = max(dp[j - ans[i].v] + ans[i].w, dp[j]);
}
}
cout << dp[w] << endl;
}
return 0;
}