zoukankan      html  css  js  c++  java
  • 【最小割】【Dinic】HihoCoder

    题意:有一个技能学习表,是一个DAG,要想正常学习到技能x,要将指向x的技能全部先学到,然后会有一个正常花费cx。然后你还有一种方案,通过氪金dx直接获得技能x。你还可以通过一定的代价,切断一条边。问你学得指定的技能N的最小代价。

    源点向每个点连接代价为cx的边,每个点拆点,内部连接代价为dx的边,然后N向汇点连接代价为无穷的边,然后每条原图中的边的容量为切断其的代价。

    容易发现,每一个割集的方案恰好对应一种学习到N的所需代价的方案。所以直接跑最小割即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long ll;
    #define INF 2147483647000ll
    #define MAXN 1005
    #define MAXM 32005
    ll cap[MAXM];
    int v[MAXM],en,first[MAXN],nex[MAXM];
    int d[MAXN],cur[MAXN];
    queue<int>q;
    int S,T;
    void Init_Dinic(){memset(first,-1,sizeof(first)); en=0;}
    void AddEdge(const int &U,const int &V,const ll &W)
    {
        v[en]=V; cap[en]=W;
        nex[en]=first[U]; first[U]=en++;
        v[en]=U; cap[en]=0;
        nex[en]=first[V]; first[V]=en++;
    }
    bool bfs()
    {
        memset(d,-1,sizeof(d)); q.push(S); d[S]=0;
        while(!q.empty())
          {
              int U=q.front(); q.pop();
              for(int i=first[U];i!=-1;i=nex[i])
                if(d[v[i]]==-1 && cap[i])
                  {
                    d[v[i]]=d[U]+1;
                    q.push(v[i]);
                  }
          }
        return d[T]!=-1;
    }
    ll dfs(int U,ll a)
    {
        if(U==T || !a) return a;
        ll Flow=0,f;
        for(int &i=cur[U];i!=-1;i=nex[i])
          if(d[U]+1==d[v[i]] && (f=dfs(v[i],min(a,cap[i]))))
            {
              cap[i]-=f; cap[i^1]+=f;
              Flow+=f; a-=f; if(!a) break;
            }
        if(!Flow) d[U]=-1;
        return Flow;
    }
    ll max_flow()
    {
        ll Flow=0,tmp=0;
        while(bfs())
          {
              memcpy(cur,first,sizeof(first));
              while(tmp=dfs(S,INF)) Flow+=tmp;
          }
        return Flow;
    }
    int n,m,nn;
    int main(){
    //	freopen("d.in","r",stdin);
    	int x,y,zu;
    	ll z;
    	scanf("%d",&zu);
    	for(;zu;--zu){
    		Init_Dinic();
    		scanf("%d%d%d",&n,&m,&nn);
    		S=n*2+1;
    		T=S+1;
    		for(int i=1;i<=m;++i){
    			scanf("%d%d%lld",&x,&y,&z);
    			AddEdge(x+n,y,z);
    		}
    		for(int i=1;i<=n;++i){
    			scanf("%lld",&z);
    			AddEdge(S,i,z);
    		}
    		for(int i=1;i<=n;++i){
    			scanf("%lld",&z);
    			AddEdge(i,i+n,z);
    		}
    		AddEdge(nn+n,T,INF);
    		printf("%lld
    ",max_flow());
    	}
    	return 0;
    }
  • 相关阅读:
    fn project 试用之后的几个问题的解答
    fn project 扩展
    fn project 生产环境使用
    fn project 对象模型
    fn project AWS Lambda 格式 functions
    fn project 打包Function
    fn project Function files 说明
    fn project hot functions 说明
    fn project k8s 集成
    fn project 私有镜像发布
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7687490.html
Copyright © 2011-2022 走看看