2018.10.21【网络流24题】【洛谷P2762】【LOJ6001】太空飞行计划(最小割)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83244522

洛谷传送门

LOJ传送门

(LOJ输出有毒,testlib对行末空格很敏感,所以我这份代码的输出不是很清真。。。)


解析:

感觉好像就是这道题的弱化版。。。

所以不如先把上面这道题A了再来做这道?

不过这里就只需要仪器向汇点连边,项目向源点连边,仪器和对应项目之间连容量为 I N F INF 的边就行了。

关于输出方案:

其实本来想记录一下每条需要的边的位置,根据最终容量计算的,后来发现不需要。

我们只需要找出最后一次 D i n i c Dinic 预处理仍然在层次图里面的就行了。 S A P SAP 似乎做法是一样的。

为什么可以这样呢?

首先,如果我们找出了合法的项目,那么由于它与仪器之间连了 I N F INF 的边,所以所有的需要的机器都会被构建在层次图里面,反之,如果一个机器不被需要,那么说明它没有为任何一个合法的项目带来帮助,应当被舍弃。

那么为什么所有合法的项目都在最终的层次图里面呢?

我在刚才链接那道题的题解里面已经解释了每条边容量的意义,这里不再赘述,直入主题。
显然最终需要选择的项目与源点之间还有残量存在。

。。。好的那么它必然会被构造进层次图里面,反之,它就没有被构造进层次图的必要了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

cs int N=102,M=3000,INF=0x3f3f3f3f;
cs int S=0,T=N-1;
int last[N],nxt[M<<1],to[M<<1],ecnt=1;
int cap[M<<1];
inline int addedge(int u,int v,int val){
	nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,cap[ecnt]=val;
	nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,cap[ecnt]=0;
	return ecnt-1;
}

int lev[N];
int cur[N];
inline bool BFS(){
	queue<int> q;
	memset(lev,-1,sizeof lev);
	lev[S]=0;
	q.push(S);
	cur[S]=last[S];
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
			if(cap[e]&&lev[v]==-1){
				lev[v]=lev[u]+1;
				if(v==T)return true;
				cur[v]=last[v];
				q.push(v);
			}
		}
	}
	return false;
}

int Dinic(cs int &u,cs int &flow){
	if(u==T)return flow;
	int ans=0;
	for(int &e=cur[u],v=to[e];e;v=to[e=nxt[e]]){
		if(cap[e]&&lev[v]>lev[u]){
			int delta=Dinic(v,min(flow-ans,cap[e]));
			if(delta){
				cap[e]-=delta;
				cap[e^1]+=delta;
				ans+=delta;
				if(ans==flow)return flow;
			}
		}
	}
	return ans;
}

inline int maxflow(){
	int ans=0;
	while(BFS())ans+=Dinic(S,INF);
	return ans;
}

int n,m,tot;
char ss[100000];
signed main(){
	scanf("%d%d",&n,&m);
	for(int re i=1;i<=n;++i){
		int val;
		scanf("%d",&val);
		tot+=val;
		addedge(S,i,val);
		cin.getline(ss,100000);
		int now=0;
		while(sscanf(ss+now,"%d",&val)==1){
			addedge(i,val+50,INF);
			do{
				++now;
				val/=10;
			}while(val);
			++now;
		}
	}
	for(int re i=1;i<=m;++i){
		int val;scanf("%d",&val);
		addedge(i+50,T,val);
	}
	int ans=tot-maxflow();
	bool flag=false;
	for(int re i=1;i<=n;++i){
		if(~lev[i]){
			if(!flag)flag=true;
			else pc(' ');
			printf("%d",i);
		}
	}
	pc('\n');
	flag=false;
	for(int re i=1;i<=m;++i){
		if(~lev[i+50]){
			if(!flag)flag=true;
			else pc(' ');
			printf("%d",i);
		}
	}
	pc('\n');
	cout<<ans;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/83244522