您的位置:首页 > 理论基础 > 计算机网络

[网络流24题] 太空飞行计划问题

2018-02-01 12:21 393 查看
这道题目的核心是模型转化

将题意反过来考虑,变成“要求选出一个实验的集合,那么这个集合所附带的器材必须选,求最大点权和”

转化为最大权闭合子图

[b]做法:[/b]

从源点向每一个实验连边,容量为实验的收益

每个实验和它依赖的仪器之间连inf边

从仪器向汇点连边,容量为仪器费用

跑S-T最大流,用实验的总收益减去最大流的值就是最大收益

具体方案的输出,在最后一次分层图bfs(就是没到达汇点的那次)中访问过的点就是选要择的

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1e9
using namespace std;
char tmpch;
inline int read(){
int re=0,flag=1;char ch=tmpch;
//if(ch=='\n'||ch=='\r') exit(0);
while(ch>'9'||ch<'0'){
/*cout<<"useless char "<<(int)ch<<"\n";*/
/*if((int)ch==-1) exit(0); */
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
tmpch=ch;
//cout<<"read in "<<re*flag<<"\n";
return re*flag;
}
int n,m,cnt=-1,ans=0,first[110],cur[110],dep[110];
struct edge{
int to,next,w;
}a[10010];
inline void add(int u,int v,int w){
//cout<<"add "<<u<<" "<<v<<" "<<w<<"\n";
a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
a[++cnt]=(edge){u,first[v],0};first[v]=cnt;
}
bool bfs(int s,int t){
int i,u,v,q[110],head=0,tail=1;
for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
dep[s]=0;q[0]=s;
while(head<tail){
u=q[head++];
//cout<<"bfs "<<u<<" "<<dep[u]<<"\n";
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(~dep[v]||!a[i].w) continue;
dep[v]=dep[u]+1;q[tail++]=v;
}
}
return ~dep[t];
}
int _min(int l,int r){return (l<r)?l:r;}
int dfs(int u,int t,int limit){
if(u==t||!limit) return limit;
int i,v,f,flow=0;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if((dep[v]==dep[u]+1)&&(f=dfs(v,t,_min(limit,a[i].w)))){
flow+=f;limit-=f;
a[i].w-=f;a[i^1].w+=f;
if(!limit) return flow;
}
}
return flow;
}
void dinic(int s,int t){
while(bfs(s,t)) ans+=dfs(s,t,inf);
}
int main(){
freopen("shuttle.in","r",stdin);
freopen("shuttle.out","w",stdout);
memset(first,-1,sizeof(first));
int i,t1,sum=0;
n=read();m=read();tmpch=0;
for(i=1;i<=n;i++){
t1=read();add(0,i,t1);sum+=t1;
tmpch=0;
//cout<<"experiment "<<i<<"\n";
while(((t1=read())||1)&&tmpch!='\n'&&tmpch!='\r') add(i,n+t1,inf);
tmpch=0;add(i,n+t1,inf);
}
//cout<<"finish experiment\n";
for(i=1;i<=m;i++) t1=read(),add(n+i,m+n+1,t1);
//cout<<"finish read in\n";tmpch=0;
dinic(0,n+m+1);
for(i=1;i<=n;i++) if(~dep[i]) printf("%d ",i);printf("\n");
for(i=1;i<=m;i++) if(~dep[n+i]) printf("%d ",i);printf("\n");
printf("%d\n",sum-ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: