zoukankan      html  css  js  c++  java
  • 太空飞行计划 最大权闭合图

    <span style="font-family: Arial, Helvetica, sans-serif;">选了一个点,必需选择其他点,故题意为求一个闭合图(闭合图:在一个图中,我们选取一些点构成集合,记为V,且集合中的出边(即集合中的点的向外连出的弧),所指向的终点(弧头)也在V中,则我们称V为闭合图。最大权闭合图即在所有闭合图中,集合中点的权值之和最大的V,我们称V为最大权闭合图。)</span>

    ,构图法:取起点s,连线去所有正权的点,所有负权的点连线到t,权值为绝对值,原图的边权值为inf,最大权=正权和-s-t最大流,最小割即为方案(最后一遍bfs求增广路后,vis[i]中可以到达的点(s集合中的,满流边过不去了)即为所取)。



    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<vector>
    #include<algorithm>
    #include<fstream>
    using namespace std;
    int n,m;int nume;int e[50000][3];int head[1005];
    const  int inf=100000;
    int vis[1005];int level[1005];
    bool bfs()
    {
        for(int i=0;i<=n+m+1;i++)
             vis[i]=level[i]=0;
        queue<int>q;q.push(0);vis[0]=1;
        while(!q.empty())
        {
            int cur=q.front();q.pop();
            for(int i=head[cur];i!=-1;i=e[i][1])
            {   int v=e[i][0];
                if(!vis[v]&&e[i][2]>0)
                {
                    level[v]=level[cur]+1;
                    if(v==n+1+m)return 1;
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
        return vis[n+1+m];
    }
    int dfs(int u,int minf)
    {
        if(minf==0||u==n+1+m)return minf;
        int sumf=0,f;
        for(int i=head[u];i!=-1&&minf;i=e[i][1])
        {
             int v=e[i][0];
            if(level[v]==level[u]+1&&e[i][2]>0)
            {
                f=dfs(v,minf<e[i][2]?minf:e[i][2]);
                e[i][2]-=f;e[i^1][2]+=f;
                minf-=f;sumf+=f;
            }
        }
        return sumf;
    }
    void addedge (int f,int to,int w)
    {
        e[nume][0]=to;e[nume][1]=head[f];head[f]=nume;
        e[nume++][2]=w;
        e[nume][0]=f;e[nume][1]=head[to];head[to]=nume;
        e[nume++][2]=0;
    }
    int dinic()
    {
        int sum=0;
        while(bfs())
           sum+=dfs(0,inf);
       return sum;
    }
    vector<int>vv;
    int main()
     {
         // ifstream cin("shuttle.in");
         //  ofstream out("shuttle.out");
        cin>>m>>n;
        for(int i=0;i<=m+n+1;i++)
            head[i]=-1;
            nume=0;
        int sum=0;int x,y,w;
         for(int i=1;i<=m;i++)
        {
            cin>>w;
            addedge(0,i,w);
            while(cin.peek()!='
    ')
            {
                cin>>y;
                addedge(i,y+m,inf);
            }
            sum+=w;
        }
        for(int i=m+1;i<=m+n;i++)
        {
            cin>>w;
            addedge(i,n+m+1,w);
        }
        int ans=sum-dinic();
        for(int i=1;i<n+m+1;i++)
           if(vis[i])vv.push_back(i);
        sort(vv.begin(),vv.end());
        int i;
        for(i=0;i<vv.size()&&vv[i]<=m;i++)
        {
            cout<<vv[i]<<" ";
        }
          cout<<endl;
         for(;i<vv.size();i++)
        {
            if(i==vv.size()-1)cout<<vv[i]-m<<endl;
           else cout<<vv[i]-m<<" ";
        }
        cout<<ans<<endl;
        return 0;
    }
    


  • 相关阅读:
    基于 MySQL 5.6 keepalived的双主搭建
    keepalived.conf 配置文件小结
    keepalived小结
    能不能利用复制报错,让从库停在同一个复制的位置上?
    复制介绍、复制的实用价值
    复制相关参数学习笔记--master上的参数
    计数排序
    双向链表
    约瑟夫问题
    单链表中重复元素的删除
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925799.html
Copyright © 2011-2022 走看看