• 【NOI2006T4】最大获利-最大权闭合子图(最大流)


    测试地址:最大获利

    做法:首先介绍一下闭合子图和最大权闭合子图的概念:在一个有向图中选择一个点集V,若V满足对于任意点X∈V,若有向边(X,Y)存在,则Y∈V,即V中所有点的出边终点也属于V,则称V为一个闭合子图,最大权闭合子图就是在原图有点权的情况下,在所有闭合子图中点权和最大的一个闭合子图。因为点权可能有正有负,所以不能简单粗暴的求解,但是我们可以将其转化为求最小割的问题,进而转化为求最大流的问题,转化方法可以看这里

    那么我们就可以很容易的看出这个题目就是一个最大权闭合子图的模型,要选择用户群,也必须选择该用户群所需的中转站,则从用户群向其所需的中转站连边,然后按照以上模型建图求解即可。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #define inf 1000000000
    using namespace std;
    int n,m,sum=0,first[60010],tot=1;
    int level[60010];
    struct edge {int v,f,next;} e[1000010];
    
    void insert(int a,int b,int f)
    {
      e[++tot].v=b,e[tot].f=f,e[tot].next=first[a],first[a]=tot;
      e[++tot].v=a,e[tot].f=0,e[tot].next=first[b],first[b]=tot;
    }
    
    bool makelevel()
    {
      queue<int> q;
      memset(level,0,sizeof(level));
      level[0]=1;
      q.push(0);
      
      while(!q.empty())
      {
        int v=q.front();q.pop();
    	for(int i=first[v];i;i=e[i].next)
    	  if (!level[e[i].v]&&e[i].f)
    	  {
    	    level[e[i].v]=level[v]+1;
    		q.push(e[i].v);
    	  }
      }
      
      return level[n+m+1];
    }
    
    int dfs(int v,int maxf)
    {
      int ret=0,f;
      if (v==n+m+1) return maxf;
      for(int i=first[v];i;i=e[i].next)
        if (level[e[i].v]==level[v]+1&&e[i].f)
    	{
    	  f=dfs(e[i].v,min(maxf-ret,e[i].f)); //一定要注意减ret!!!太容易错了!
    	  e[i].f-=f;
    	  e[i^1].f+=f;
    	  ret+=f;
    	  if (ret==maxf) return ret;
    	}
      return ret;
    }
    
    int dinic()
    {
      int ans=0;
      while(makelevel())
      {
        ans+=dfs(0,inf);
      }
      return ans;
    }
    
    int main()
    {
      memset(first,0,sizeof(first));
      scanf("%d%d",&n,&m);
      for(int i=1,a;i<=n;i++)
      {
        scanf("%d",&a);
    	insert(i,n+m+1,a);
      }
      for(int i=1,a,b,c;i<=m;i++)
      {
        scanf("%d%d%d",&a,&b,&c);
    	sum+=c;
    	insert(0,n+i,c);
    	insert(n+i,a,inf);
    	insert(n+i,b,inf);
      }
      
      printf("%d",sum-dinic());
      
      return 0;
    }
    


  • 相关阅读:
    Cookie和Session机制详解
    MySQL数据库MyISAM和InnoDB存储引擎的比较
    MySQL索引背后的数据结构及算法原理
    Qt Meta Object System-元对象系统
    Qt事件处理机制
    学习STL-介绍一下STL
    为什么你有10年经验,但成不了专家?
    关于union的那些事儿
    关于enum的那些事儿
    三子棋局-挑战你的逻辑思维
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793825.html
Copyright © 2020-2023  润新知