太空飞行计划 最大权闭合图

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


原文地址:https://www.cnblogs.com/yezekun/p/3925799.html