1. 程式人生 > >洛谷P1455搭配購買

洛谷P1455搭配購買

傳送門啦

這是強連通分量與揹包的例題

需要注意的就是價值和價格兩個陣列不要打反了。。

另外 這是雙向圖!!!

#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;
}