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