太空飞行计划问题(网络流24题,七)

来源:互联网 发布:微软办公软件国际认证 编辑:程序博客网 时间:2024/05/16 14:05


                                              太空飞行计划问题


题目分析:

   是一道中问题,就不深入的分析了。就是叫你求给你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;}   






4 0
原创粉丝点击