P2762 太空飞行计划问题

题目链接

题意分析

这道题其实就是一个裸的最大权闭合子图问题

如果把实验看作一个点的话 ta的出度连接着的点就是ta对应的仪器 符合闭合子图的概念

那么我们建好图之后就可以跑最小割最大流了

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 500008
#define IL inline
#define M 1008611
#define D double
#define ull unsigned long long
#define R register
using namespace std;
bool flag;
/*-------------OI使我快乐-------------*/
queue<int> Q;
int n,m,tot=1,S,T,ans,sum;
int val[N],need[100][100],cost[N],dep[N],fro[N];
int to[N],nex[N],head[N],w[N];
IL void add(int x,int y,int z)
{to[++tot]=y;nex[tot]=head[x];head[x]=tot;w[tot]=z;}
IL bool CDY(int &res)
{
    res=0;char ch=getchar();
    while(!isdigit(ch)) if(ch=='\n') return 0;else ch=getchar();
    while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
    if(ch=='\n') return 0;else return 1;
}
IL bool bfs()
{
    for(R int i=1;i<=(n+m+10);++i) dep[i]=0;
    dep[S]=1;Q.push(S);
    for(;!Q.empty();)
    {
        int u=Q.front();Q.pop();
        for(R int i=head[u];i;i=nex[i])
        {
            int v=to[i];
            if(w[i]>0&&dep[v]==0)
            {
                dep[v]=dep[u]+1;
                Q.push(v);
            }
        }
    }
    return dep[T]!=0;
}
IL int dfs(int now,int res)
{
    if(now==T) return res;
    for(R int &i=fro[now];i;i=nex[i])
    {
        int v=to[i];
        if(w[i]&&dep[v]==dep[now]+1)
        {
            int have=dfs(v,min(res,w[i]));
            if(have>0)
            {
                w[i]-=have;w[i^1]+=have;return have;
            }
        }
    }
    return 0;
}
IL void Dinic()
{
    while(bfs())
    {
        for(R int i=1;i<=(n+m)+10;++i) fro[i]=head[i];
        int can=dfs(S,inf);
        while(can) ans+=can,can=dfs(S,inf);
    }
}
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
    scanf("%d%d",&n,&m);S=n+m+1;T=n+m+2;
    for(R int i=1,x;i<=n;++i)
    {
    	scanf("%d",&x);sum+=x;
    	add(S,i,x);add(i,S,0);
    	while(CDY(x)) add(i,x+n,inf),add(x+n,i,0);
    	add(i,x+n,inf),add(x+n,i,0);
    }
    for(R int i=1,x;i<=m;++i) scanf("%d",&x),add(i+n,T,x),add(T,i+n,0);
    Dinic();
    for(R int i=1;i<=n;++i) if(dep[i]>0) printf("%d ",i);printf("\n");
    for(R int j=1;j<=m;++j) if(dep[j+n]>0) printf("%d ",j);printf("\n");
    printf("%d\n",sum-ans);
//	fclose(stdin);
//	fclose(stdout);
    return 0;
}
posted @ 2020-10-11 10:03  tcswuzb  阅读(136)  评论(0编辑  收藏  举报