zoukankan      html  css  js  c++  java
  • 太空飞行计划问题

    http://www.wikioi.com/problem/1233/

    网络流最小费用问题
    一开始看这个人的博客: http://blog.sina.com.cn/s/blog_61034ad90100eine.html,写了4天了,还是没能写出自己的代码。。。
    后面面还有在这个OJ上AC了的代码。

    照着这个人的代码打,还是没能想明白。。这个代码和这个OJ上的不同,是简化问题了的。只求最大收益
    照着打的代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define INF 999999
    using namespace std;
    //分别为残余网络,返回值,当前枚举的点,当前点的前驱,当前点到汇点的距离,距离为I的点数
    int a[500][500],fh[500],now[500],pre[500],dis[500],sumd[500];
    int n,m,ans;      //仪器数,实验数,收入
    queue<int> q;
    
    void cl()
    {
        ans = 0;
        memset(a,0,sizeof(a));
        memset(fh,0,sizeof(fh));
        memset(now,0,sizeof(now));
        memset(pre,0,sizeof(pre));
        memset(dis,0,sizeof(dis));
        memset(sumd,0,sizeof(sumd));
        return ;
    }
    
    void input()
    {
        int i,j,p;
        for(i = 1; i <= m; i++)
        {
            scanf("%d",&a[0][i]);  //原点为0第t个实验的收益
            ans+=a[0][i];          //累加收入
            while(scanf("%d",&p)&&p)
            {
                a[i][p+m] = INF;     //每个实验所需的实验仪器,t为实验编号,p为所需仪器编号
            }
        }
        for(i = m+1; i <= n+m; i++)
        {
            scanf("%d",&a[i][n+m+1]); //每个实验器材的成本,汇点为n+m
        }
        n = m+n+1;     //汇聚点更改
        return ;
    }
    
    void sap()
    {
        int i,j,k,flow,minn;
        bool flag;
        sumd[0] = n+1;
        i = 0;
        flow = INF;
        while(dis[0] < n)
        {
            fh[i] = flow;  //保存返回值
            flag = false;
            for(j = now[i]; j <= n; j++)
            {
                if(a[i][j] > 0 && dis[i] == dis[j])   //满足有边,且距离之差为1
                {
                    now[i] = j;  //更新访问节点
                    flag = true;
                    if(a[i][j]<flow)//更改该路上可通行的流量
                    {
                        flow = a[i][j];
                    }
                    pre[j] = i;//记录前驱
                    i = j;
                    if(i == n)
                    {
                        ans-=flow;   //减去这个流量
                        while(i!=0)
                        {
                            k = pre[i];
                            a[k][i]-=flow;
                            a[i][k]+=flow;
                            i = k;
                        }
                    }
                    break;
                }
            }
            if(flag)
            {
                continue;  //找不到增广路,不修改
            }
            minn = n+1;  //赋值为最大距离
            for(j = 0; j<=n; j++)
            {
                if(a[i][j]>0&&dis[j]<minn)
                {
                    minn = dis[j];   //找到最小距离的点
                    now[i] = j;      //更新前驱
                }
            }
            sumd[dis[i]]--;   //到该距离的总点数减一
            if(sumd[dis[i]]==0)    break;//中间没有点,有断层,无法找到增广路
            dis[i] = minn+1;  //距离加一
            sumd[dis[i]]++;   //到该距离的总点数加一
            if(i!=0)
            {
                i = pre[i];  //当前状态以改变,返回上一层
                flow = fh[i];
            }
        }
        printf("%d
    ",ans);
        return ;
    }
    
    int main()
    {
        while(scanf("%d%d",&m,&n)!=EOF)
        {
            cl();//初始化清空
            input();//输入数据
            /*for(int i=0; i<=m+n;i++)
            {
                for(int j=0; j<=m+n;j++)
                {
                    printf("%6d ",a[i][j]);
                }
                printf("
    ");
            }*/
            sap();
        }
    
        return 0;
    }
    

    在这个OJ网站上下的别人AC代码,慢慢看把。。T_T。。
    代码:
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<iostream>
    #define MAXL 1010
    #define MAXN 100010
    #define MAXM 1000010
    #define oo 0x7FFFFFFF
    using namespace std;
    int first[MAXN], next[MAXM], v[MAXM], cost[MAXM], e;
    int n;
    int src, des;
    
    bool flag;
    bool vis[MAXL];
    char str[MAXN];
    vector<int> g[MAXL];
    vector<int> test;
    vector<int> app;
    int a[MAXL];
    inline void addEdge(int x, int y, int val)
    {
        v[e] = y;
        cost[e] = val;
        next[e] = first[x];
        first[x] = e++;
    
        v[e] = x;
        cost[e] = 0;
        next[e] = first[y];
        first[y] = e++;
    }
    int SAP()
    {
        int pre[MAXN], cur[MAXN], dis[MAXN], gap[MAXN];
        int flow = 0;
        int aug = oo;
        int x, y;
        bool flag;
        for (int i = 0; i < n; i++)
        {
            cur[i] = first[i];
            gap[i] = dis[i] = 0;
        }
        gap[src] = n;
        x = pre[src] = src;
        while (dis[src] < n)
        {
            flag = false;
            for (int &j = cur[x]; j != -1; j = next[j])
            {
                y = v[j];
                if (cost[j] > 0 && dis[x] == dis[y] + 1)
                {
                    flag = true;
                    aug = min(aug, cost[j]);
                    pre[y] = x;
                    x = y;
                    if (x == des)
                    {
                        flow += aug;
                        while (x != src)
                        {
                            x = pre[x];
                            cost[cur[x]] -= aug;
                            cost[cur[x] ^ 1] += aug;
                        }
                        aug = oo;
                    }
                    break;
                }
            }
            if (flag)
            {
                continue;
            }
            int tmp = n;
            for (int j = first[x]; j != -1; j = next[j])
            {
                y = v[j];
                if (cost[j] > 0 && dis[y] < tmp)
                {
                    tmp = dis[y];
                    cur[x] = j;
                }
            }
            if ((--gap[dis[x]]) == 0)
            {
                break;
            }
            gap[dis[x] = tmp + 1]++;
            x = pre[x];
        }
        return flow;
    }
    void out(vector<int> res)
    {
        int i;
        sort(res.begin(), res.end());
        res.resize(unique(res.begin(), res.end()) - res.begin());
        for (i = 0; i < (int) res.size(); i++)
        {
            if (i)
            {
                putchar(' ');
            }
            printf("%d", res[i]);
        }
        putchar('
    ');
    }
    void dfs(int x)
    {
        int i;
        vis[x] = true;
        if (x == des)
        {
            flag = false;
        }
        for (i = first[x]; i != -1; i = next[i])
        {
            if (!vis[v[i]] && cost[i] > 0)
            {
                dfs(v[i]);
            }
        }
    }
    int main()
    {
        int m;
        int i, j, k;
        int len;
        int ans;
        while (~scanf("%d%d", &m, &n))
        {
            src = 0;
            des = n + m + 1;
            e = 0;
            memset(first, -1, sizeof(first));
            gets(str);
            for (i = 1; i <= m; i++)
            {
                g[i].clear();
                gets(str);
                len = strlen(str);
                for (j = 0; j < len; j++)
                {
                    for (; j < len && str[j] == ' '; j++);
                    if (j < len)
                    {
                        sscanf(str + j, "%d", &k);
                        g[i].push_back(k);
                    }
                    for (; j < len && isdigit(str[j]); j++)
                        ;
                }
            }
            for (i = 1; i <= n; i++)
            {
                scanf("%d", &a[i]);
                addEdge(m + i, des, a[i]);
            }
            ans = 0;
            for (i = 1; i <= m; i++)
            {
                addEdge(src, i, g[i][0]);
                ans += g[i][0];
                for (j = 1; j < (int) g[i].size(); j++)
                {
                    addEdge(i, m + g[i][j], oo);
                }
            }
            n = des + 1;
            ans -= SAP();
            test.clear();
            app.clear();
            for (i = first[src]; i != -1; i = next[i])
            {
                k = v[i];
                flag = true;
                memset(vis, false, sizeof(vis));
                dfs(k);
                if (flag)
                {
                    test.push_back(k);
                    for (j = 1; j < (int) g[k].size(); j++)
                    {
                        app.push_back(g[k][j]);
                    }
                }
            }
            out(test);
            out(app);
            printf("%d
    ", ans);
        }
        return 0;
    }
    


  • 相关阅读:
    认证-权限-频率组件
    视图组件
    序列化类
    解析模块
    异常模块
    响应模块分析
    请求模块分析
    cbv请求分析
    django中的restful规范
    web接口与restful规范
  • 原文地址:https://www.cnblogs.com/james1207/p/3262789.html
Copyright © 2011-2022 走看看