zoukankan      html  css  js  c++  java
  • 1737: 太空飞行计划问题 最大权闭合子图

    1、建立两个超级点S,T。

    2、对每个实验跟S链接一条容量为收入的边。

    3、对每个一起跟T链接一条容量为花费的边。

    4、对每个实验要用到的一起链接一条容量为无穷大的边。

    链表

    #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=='
    ') break;
    //            while(c!=' '&&c!='
    '){
    //                sum *= 10;
    //                sum += c - '0';
    //                c = getchar();
    //            }              printf("sum ==  %d
    ",sum);
    //            addedge(i,sum+M,INF);
    //            if(c=='
    ') 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('
    ');
        for(int i = M+1;i <= M+N;++i)
            if(Lv[i]!=-1)
               printf("%d ",i-M);
        Ans -= Maxflow;
        printf("
    %d
    ",Ans);
    }
    int main()
    {
    //    freopen("Input.txt","r",stdin);
        while(~scanf("%d%d",&M,&N)){
            Clear();
            init();
            Dinic();
            print();
        }
        return 0;
    }
     
      

    容器实现

    #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('
    ');
        for(i = M+1;i <= M+N;++i)
           if(vst[i])
              printf("%d ",i-M);
        printf("
    %d
    ",ans-maxflow);
    }
    int main()
    {
    //    freopen("Input.txt","r",stdin);
        while(~scanf("%d%d",&M,&N)){
            Init();
            Solve();
        }
        return 0;
    }
     
      
  • 相关阅读:
    Poj 1742 Coins(多重背包)
    Poj 2350 Above Average(精度控制)
    求二进制数中1的个数
    Poj 1659 Distance on Chessboard(国际象棋的走子规则)
    Poj 2411 Mondriaan's Dream(压缩矩阵DP)
    Poj 2136 Vertical Histogram(打印垂直直方图)
    Poj 1401 Factorial(计算N!尾数0的个数——质因数分解)
    poj 2390 Bank Interest(计算本利和)
    Poj 2533 Longest Ordered Subsequence(LIS)
    Poj 1887 Testing the CATCHER(LIS)
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7528578.html
Copyright © 2011-2022 走看看