1. 程式人生 > >【網絡流24題】太空飛行計劃問題(網絡流)

【網絡流24題】太空飛行計劃問題(網絡流)

string include nic body push void 如何 ems read

【網絡流24題】太空飛行計劃問題(網絡流)

題面

Cogs

題解

先假設一開始拿下所有的實驗
現在要做的也就是讓減去的所有收益最少

所以,現在考慮如何求減去的最少收益
每個實驗是兩種選擇:
要麽選,要麽不選
所以想到了最小割

因為選了實驗就必須選器材
所以從實驗向器材連容量為INF的邊

源點向所有的實驗連邊,流量為實驗的報酬
把所有器材向匯點連邊,流量為器材的費用

考慮這個時候算出來的最小割
因為中間的邊不能割,所以如果選了某個實驗,相應的器材一定要選
如果不做某個實驗,割開了實驗的報酬的邊
此時就相當於少獲得了這麽多錢
如果使用了某個器材,就會割開器材的費用的邊
表示這個器材要額外話費這麽多前

這麽考慮下來,也就是說,
算出來的最大流,也就是最小割
等於我們能夠減少的最少的報酬
因此所有實驗的報酬和減去最大流就是答案

至於方案和讀入就自行考慮了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
#define INF 1000000000
#define MAX 1000
#define MAXL MAX*MAX
inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'){t=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*t; } struct Line { int
v,next,w,fb; }e[MAXL]; int h[MAX],cnt=1; int N,level[MAX],n,m,x,Sum=0; bool vis[MAX]; queue<int> Q; int T; char s[10000]; inline void Add(int u,int v,int w) { e[cnt]=(Line){v,h[u],w,cnt+1}; h[u]=cnt++; e[cnt]=(Line){u,h[v],0,cnt-1}; h[v]=cnt++; } inline bool BFS() { for(int i=1;i<=N;++i)vis[i]=false; for(int i=1;i<=N;++i)level[i]=0; level[1]=1; while(!Q.empty())Q.pop(); Q.push(1); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(e[i].w&&!level[v]) { level[v]=level[u]+1; vis[v]=true; Q.push(v); } } } return level[T]; } int DFS(int u,int f) { if(u==T||f==0)return f;//到達終點或者無法增廣 int re=0; for(int i=h[u];i;i=e[i].next) { int v=e[i].v,d; if(e[i].w&&level[v]==level[u]+1) { d=DFS(v,min(f,e[i].w)); re+=d; f-=d; e[i].w-=d; e[e[i].fb].w+=d; } } return re; } int Dinic() { int tt=0; T=n+m+2; while(BFS()) tt+=DFS(1,INF+INF); return tt; } int main() { freopen("shuttle.in","r",stdin); freopen("shuttle.out","w",stdout); n=read();m=read(); N=n+m+2; for(int i=1;i<=n;++i) { int v=read(); Add(1,i+1,v); Sum+=v; memset(s,0,sizeof(s)); cin.getline(s,10000); int j=0; while(sscanf(s+j,"%d",&x)==1) { if(!x)j++; else Add(i+1,x+n+1,INF); while(x)x/=10,j++; j++; } } for(int i=1;i<=m;++i) { int v=read(); Add(i+n+1,n+m+2,v); } int Ans=Dinic(); for(int i=1;i<=n;++i) if(vis[i+1])printf("%d ",i); printf("\n"); for(int i=1;i<=m;++i) if(vis[i+n+1])printf("%d ",i); printf("\n"); printf("%d\n",Sum-Ans); return 0; }

【網絡流24題】太空飛行計劃問題(網絡流)