太空飞行计划问题(网络流24题,七)
2014-04-15 10:14
363 查看
太空飞行计划问题
题目分析:
是一道中问题,就不深入的分析了。就是叫你求给你M个实验,N个仪器。每个实验要用到N个仪器中的一些,而每个仪使用每个仪器都要花费一些钱。而完成每个实验会有一定的报酬,现在叫你求出最大的利润。
利润 = 总收益 - 总花费
算法分析:
最大权闭合子图。
建模分析:
我们可以根据最大闭合子图的算法思想,建立一个图。
1、我们建立两个超级点S,T。
2、对每个实验跟S链接一条容量为收入的边。
3、对每个一起跟T链接一条容量为花费的边。
4、对每个实验要用到的一起链接一条容量为无穷大的边。
C语言链表实现:
C++容器实现:
#include <iostream>
#include <algorithm>
#include <sstream>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e3 + 5,INF = ~0U >> 2;
struct Edge{
int from,to,cap,flow;
Edge(int f,int t,int c,int _f)
:from(f),to(t),cap(c),flow(_f){};
};
vector<Edge> edges;
vector<int> G[MAXN];
int N,M,S,T;
int d[MAXN],cur[MAXN];
bool vst[MAXN];
void Init()
{
for(int i = 0;i < MAXN;++i)
G[i].clear();
edges.clear();
}
inline void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int sz = edges.size();
G[from].push_back(sz-2);
G[to].push_back(sz-1);
}
bool BFS()
{
memset(vst,false,sizeof(vst));
queue<int> Q;
Q.push(S);
d[S] = 0;
vst[S] = true;
while(!Q.empty()){
int x = Q.front();
Q.pop();
for(int i = 0;i < (int)G[x].size();++i){
Edge& e = edges[G[x][i]];
if(!vst[e.to]&&e.cap>e.flow){
vst[e.to] = true;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vst[T];
}
int DFS(int u,int a)
{
if(u==T||a==0)
return a;
int f,flow = 0;
for(int& i = cur[u];i < (int)G[u].size();++i){
Edge& e = edges[G[u][i]];
if(d[u]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
e.flow += f;
edges[G[u][i]^1].flow -= f;
flow += f;
a -= f;
if(a==0)break;
}
}
return flow;
}
int Maxflow()
{
int flow = 0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow += DFS(S,INF);
}
return flow;
}
void Solve()
{
int i,c,ans = 0;
S = 0; T = M+N+1;
for(i = 1;i <= M;++i){
scanf("%d",&c);
AddEdge(S,i,c);
ans += c;
string str;
getline(cin,str);
istringstream ssin(str);
while(ssin>>c)
AddEdge(i,c+M,INF);
}
for(i = 1;i <= N;++i){
scanf("%d",&c);
AddEdge(i+M,T,c);
}
int maxflow = Maxflow();
for(i = 1;i <= M;++i)
if(vst[i])
printf("%d ",i);
putchar('\n');
for(i = M+1;i <= M+N;++i)
if(vst[i])
printf("%d ",i-M);
printf("\n%d\n",ans-maxflow);
}
int main()
{
// freopen("Input.txt","r",stdin);
while(~scanf("%d%d",&M,&N)){
Init();
Solve();
}
return 0;
}
太空飞行计划问题
题目分析:
是一道中问题,就不深入的分析了。就是叫你求给你M个实验,N个仪器。每个实验要用到N个仪器中的一些,而每个仪使用每个仪器都要花费一些钱。而完成每个实验会有一定的报酬,现在叫你求出最大的利润。
利润 = 总收益 - 总花费
算法分析:
最大权闭合子图。
建模分析:
我们可以根据最大闭合子图的算法思想,建立一个图。
1、我们建立两个超级点S,T。
2、对每个实验跟S链接一条容量为收入的边。
3、对每个一起跟T链接一条容量为花费的边。
4、对每个实验要用到的一起链接一条容量为无穷大的边。
C语言链表实现:
#include <iostream> #include <queue> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 101,MAXM = MAXN*MAXN*2,INF = ~0U >> 1; struct Edge{ Edge *next,*op; int t,c; }*V[MAXN],*P[MAXN],ES[MAXM],*Stae[MAXN]; int N,M,S,T,EC,Ans,Maxflow; int Lv[MAXN],Stap[MAXN]; void Clear() { for(int i = 0;i < MAXN;++i) V[i] = NULL,ES[i].next = NULL,ES[i].op = NULL; EC = 0; Ans = 0; Maxflow = 0; } inline void addedge(int a,int b,int c) { ES[++EC].next = V[a];V[a] = ES+EC;V[a]->t = b;V[a]->c = c; ES[++EC].next = V[b];V[b] = ES+EC;V[b]->t = a;V[b]->c = 0; V[a]->op = V[b]; V[b]->op = V[a]; } bool Dinic_Lable() //构造层次图 { int head,tail,i,j; Stap[head=tail=0] = S; memset(Lv,-1,sizeof(Lv)); Lv[S] = 0; while(head<=tail){ i = Stap[head++]; for(Edge *e = V[i];e;e = e->next){ j = e->t; if(e->c&&Lv[j]==-1){ Lv[j] = Lv[i] + 1; if(j==T) return true; Stap[++tail] = j; } } } return false; } void Dinic_Augment() //增广 { int i,j,delta,Stop; for(i = S;i <= T;++i) P[i] = V[i]; Stap[Stop=1] = S; while(Stop){ i = Stap[Stop]; if(i != T){ for(;P[i];P[i] = P[i]->next) if(P[i]->c&&Lv[i]+1==Lv[j=P[i]->t]) break; if(P[i]){ Stap[++Stop] = j; Stae[Stop] = P[i]; } else Stop--,Lv[i] = -1; } else { delta = INF; for(i = Stop;i >= 2;--i) if(Stae[i]->c < delta) delta = Stae[i]->c; Maxflow += delta; for(i = Stop;i >= 2;--i){ Stae[i]->c -= delta; Stae[i]->op->c += delta; if(Stae[i]->c == 0) Stop = i-1; } } } } void Dinic() { while(Dinic_Lable()) Dinic_Augment(); } void init() { int i,a,c; S = 0; T = M+N+1; for(i = 1;i <= M;++i){ scanf("%d",&c); addedge(S,i,c); Ans += c; // for(;;){ // int sum = 0; // c = getchar(); // while(c == ' ')c = getchar(); // if(c=='\n') break; // while(c!=' '&&c!='\n'){ // sum *= 10; // sum += c - '0'; // c = getchar(); // } printf("sum == %d\n",sum); // addedge(i,sum+M,INF); // if(c=='\n') break; // } for (;;){ while((c=getchar())==' '); ungetc(c,stdin); if (c==10 || c==13) break; scanf("%d",&a); addedge(i,a+M,INF); } } for(i = 1;i <= N;++i){ scanf("%d",&c); addedge(i+M,T,c); } } void print() { for(int i = 1;i <= M;++i) if(Lv[i]!=-1) printf("%d ",i); putchar('\n'); for(int i = M+1;i <= M+N;++i) if(Lv[i]!=-1) printf("%d ",i-M); Ans -= Maxflow; printf("\n%d\n",Ans); } int main() { // freopen("Input.txt","r",stdin); while(~scanf("%d%d",&M,&N)){ Clear(); init(); Dinic(); print(); } return 0; }
C++容器实现:
#include <iostream>
#include <algorithm>
#include <sstream>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e3 + 5,INF = ~0U >> 2;
struct Edge{
int from,to,cap,flow;
Edge(int f,int t,int c,int _f)
:from(f),to(t),cap(c),flow(_f){};
};
vector<Edge> edges;
vector<int> G[MAXN];
int N,M,S,T;
int d[MAXN],cur[MAXN];
bool vst[MAXN];
void Init()
{
for(int i = 0;i < MAXN;++i)
G[i].clear();
edges.clear();
}
inline void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int sz = edges.size();
G[from].push_back(sz-2);
G[to].push_back(sz-1);
}
bool BFS()
{
memset(vst,false,sizeof(vst));
queue<int> Q;
Q.push(S);
d[S] = 0;
vst[S] = true;
while(!Q.empty()){
int x = Q.front();
Q.pop();
for(int i = 0;i < (int)G[x].size();++i){
Edge& e = edges[G[x][i]];
if(!vst[e.to]&&e.cap>e.flow){
vst[e.to] = true;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vst[T];
}
int DFS(int u,int a)
{
if(u==T||a==0)
return a;
int f,flow = 0;
for(int& i = cur[u];i < (int)G[u].size();++i){
Edge& e = edges[G[u][i]];
if(d[u]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
e.flow += f;
edges[G[u][i]^1].flow -= f;
flow += f;
a -= f;
if(a==0)break;
}
}
return flow;
}
int Maxflow()
{
int flow = 0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow += DFS(S,INF);
}
return flow;
}
void Solve()
{
int i,c,ans = 0;
S = 0; T = M+N+1;
for(i = 1;i <= M;++i){
scanf("%d",&c);
AddEdge(S,i,c);
ans += c;
string str;
getline(cin,str);
istringstream ssin(str);
while(ssin>>c)
AddEdge(i,c+M,INF);
}
for(i = 1;i <= N;++i){
scanf("%d",&c);
AddEdge(i+M,T,c);
}
int maxflow = Maxflow();
for(i = 1;i <= M;++i)
if(vst[i])
printf("%d ",i);
putchar('\n');
for(i = M+1;i <= M+N;++i)
if(vst[i])
printf("%d ",i-M);
printf("\n%d\n",ans-maxflow);
}
int main()
{
// freopen("Input.txt","r",stdin);
while(~scanf("%d%d",&M,&N)){
Init();
Solve();
}
return 0;
}
相关文章推荐
- 【网络流24题】太空飞行计划问题
- 线性规划与网络流24题 太空飞行计划问题 (最小割及输出方案)
- 网络流24题2 太空飞行计划问题
- [网络流24题 #2]太空飞行计划问题
- [网络流24题 #2]太空飞行计划问题
- 【网络流24题】太空飞行计划问题(网络流)
- 网络流24题2 太空飞行计划问题 洛谷 2762
- [网络流24题] 太空飞行计划问题
- 网络流24题 太空飞行计划问题___最大权闭合子图
- 线性规划与网络流24题 02太空飞行计划问题
- 【网络流24题】 No.2 太空飞行计划问题 (最大闭合权图 最大流 )
- 【网络流24题】太空飞行计划问题 …
- 线性规划与网络流24题 02太空飞行计划问题 最小割
- [网络流24题][洛谷P2762]太空飞行计划问题
- 【网络流24题】太空飞行计划问题
- 最大流——Luogu2762 [网络流24题]太空飞行计划问题
- P2762 太空飞行计划问题(网络流24题之一)
- 网络流24题之太空飞行计划问题(nefu476)
- loj #6001. 「网络流 24 题」太空飞行计划(最大权闭合子图)
- COGS727 [网络流24题] 太空飞行计划