传送门啦

这是强连通分量与背包的例题

需要注意的就是价值和价格两个数组不要打反了。。

另外 这是双向图!!!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e4 + 4;
const int maxm = 5005; int n,m,mon;
int c[maxn],w[maxn],u,v;
int C[maxn],W[maxn],f[maxn];
int head[maxn],tot;
int dfn[maxn],low[maxn],ind;
int num[maxn],belong[maxn],cnt,stack[maxn],top;
bool ins[maxn];
struct Edge{
int to,next,from;
}edge[maxm << 1]; void add(int u,int v){
edge[++tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
} int read(){
char ch = getchar();
int f = 1 , x = 0;
while(ch > '9' || ch < '0'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
} void tarjan(int x){
dfn[x] = low[x] = ++ind;
stack[++top] = x;
ins[x] = true;
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
if(!dfn[v]){
tarjan(v);
low[x] = min(low[x] , low[v]);
}
else if(ins[v]) low[x] = min(low[x] , dfn[v]);
}
int k = 0;
if(dfn[x] == low[x]){
++cnt;
do{
k = stack[top];
num[cnt]++;
top--;
ins[k] = false;
belong[k] = cnt;
C[cnt] += c[k];
W[cnt] += w[k];
} while(k != x);
}
} int main(){
n = read(); m = read(); mon = read();
for(int i=1;i<=n;i++){
c[i] = read(); w[i] = read();
}
for(int i=1;i<=m;i++){
u = read(); v = read();
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=cnt;i++)
for(int j=mon;j>=C[i];j--)
f[j] = max(f[j] , f[j - C[i]] + W[i]);
printf("%d",f[mon]);
return 0;
}
05-11 17:23