hdu 6501 transaction transaction transaction 最长路/树形DP/网络流

最长路:

设置一个虚拟起点和虚拟终点,每个点与起点间一条负边,值为这个点书的价值的相反数(代表买书花钱),每个点与终点连一条正边,值为这个点的书的价格(代表卖书赚钱)。

然后按照图中给的边建无向边,权值为负(代表路费)。跑最长路,spfa改一下松弛条件就行

#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 100000+10;
const int inf = 1e9;
int n;
int cost[100000+10];
struct node
{
    int to;
    int w;
    node(int a,int b):to(a),w(b){}
};
vector<node>G[maxn];
int dist[maxn],vis[maxn];
void spfa()
{
    queue<int>q;
    for(int i=0;i<=n+1;i++) dist[i] = -inf;
    memset(vis,0,sizeof(vis));
    q.push(0); vis[0] = 1; dist[0] = 0;
    while(!q.empty())
    {
        int u = q.front(); q.pop(); int len = G[u].size();
        for(int i=0;i<len;i++)
        {
            int v = G[u][i].to;
            int w = G[u][i].w;
            if(dist[v]<dist[u]+w)
            {
                dist[v] = dist[u] + w;
                if(!vis[v]){vis[v] = 1; q.push(v); }
            }
        }
        vis[u] = 0;
    }
    printf("%d\n",dist[n+1]);
}
int main()
{
    int cases,u,v,w;
    scanf("%d",&cases);
    while(cases--)
    {
        scanf("%d",&n);
        for(int i=0;i<n+5;i++) G[i].clear();
        for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
        for(int i=1;i<=n;i++)
        {
            G[0].push_back(node(i,-cost[i]));
            G[i].push_back(node(n+1,cost[i]));
        }
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            G[u].push_back(node(v,-w));
            G[v].push_back(node(u,-w));
        }
        spfa();
    }
    return 0;
}

树形DP:

设1为根节点,假设一开始一个人身上的钱为0。

我们设dp[i][0]表示从根节点走到i及其子树并中任一点买入一本书后这个人身上钱的最大值(显然是负的)。

dp[i][1]表示从根节点走到i及其子树并中任一点卖出一本书后这个人身上钱的最大值(可正可负)。

那么我们对这棵树进行一次树形DP即可,dfs后对每个节点更新收益最大值,单点的计算方法为:w=dp[i][0]+dp[i][1]

(由于前者是负的,相当于收入减去总花费)

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 100005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;

struct node
{
    int v,w;
    node(int _v,int _w):v(_v),w(_w) {}
};

int n,ans;
int val[maxn];
int dp[maxn][2];
vector<node>vec[maxn];

void dfs(int u,int pre)
{
    dp[u][0]=-val[u];
    dp[u][1]=val[u];
    for(int i=0;i<vec[u].size();i++)
    {
        int v=vec[u][i].v;
        int w=vec[u][i].w;
        if(v==pre) continue;
        dfs(v,u);
        dp[u][0]=max(dp[u][0],dp[v][0]-w);
        dp[u][1]=max(dp[u][1],dp[v][1]-w);
    }
    ans=max(ans,dp[u][0]+dp[u][1]);
}

int main()
{
    int u,v,w;
    rush()
    {
        scanf("%d",&n);
        for(int i=0;i<=n;i++)
        {
            vec[i].clear();
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
        }
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            vec[u].push_back(node(v,w));
            vec[v].push_back(node(u,w));
        }
        ans=0;
        dfs(1,-1);
        printf("%d\n",ans);
    }
    return 0;
}

网络流:

直接构图 费用流跑一遍

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string.h>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
typedef long long ll;
typedef unsigned long long LL;
using namespace std;
const double PI=acos(-1.0);
const double eps=0.0000000001;
const int INF=0x3f3f3f3f;
const int N=1000000+100;
int a[N];
int head[N];
int dis[N];
int pre[N];
int vis[N];
int tot;
int m,n;
struct node{
    int from,to,next,flow,cost;
}edge[N<<1];
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
void add(int u,int v,int c,int cost){
    edge[tot].from=u;
    edge[tot].to=v;
    edge[tot].flow=c;
    edge[tot].cost=cost;
    edge[tot].next=head[u];
    head[u]=tot++;
    edge[tot].from=v;
    edge[tot].to=u;
    edge[tot].flow=0;
    edge[tot].cost=-cost;
    edge[tot].next=head[v];
    head[v]=tot++;
}
int spfa(int s,int t){
    memset(pre,-1,sizeof(pre));
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int>q;
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].flow&&dis[v]>dis[x]+edge[i].cost){
                dis[v]=edge[i].cost+dis[x];
                pre[v]=i;
                if(vis[v]==0){
                    vis[v]=1;
                    q.push(v);
                }

            }
        }
    }
    if(pre[t]==-1)return 0;
    return 1;
}
int MCMF(int s,int t){
    int flow=0;
    int cost=0;
    while(spfa(s,t)){
        int minn=INF;
        for(int i=pre[t];i!=-1;i=pre[edge[i].from]){
            minn=min(minn,edge[i].flow);
        }
        for(int i=pre[t];i!=-1;i=pre[edge[i].from]){
            edge[i].flow=edge[i].flow-minn;
            edge[i^1].flow=edge[i^1].flow+minn;
            cost=edge[i].cost+cost;
           // cout<<cost<<endl;
        }
        flow=flow+minn;
    }
    return cost;
}
int main(){
    int tt;
    scanf("%d",&tt);
    while(tt--){
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        int s=0;
        int s1=n+1;
        int t=n+2;
        add(s,s1,1,0);
        for(int i=1;i<=n;i++){
            add(s1,i,1,-a[i]);
        }
        for(int i=1;i<=n;i++){
            add(i,t,1,a[i]);
        }
        for(int i=1;i<=n-1;i++){
            int u,v,cost;
            scanf("%d%d%d",&u,&v,&cost);
            add(u,v,1,cost);
            add(v,u,1,cost);
        }
        cout<<abs(MCMF(s,t))<<endl;
    }
}

 

posted @ 2017-09-14 14:18  Aragaki  阅读(342)  评论(0编辑  收藏  举报