zoukankan      html  css  js  c++  java
  • bzoj2879(动态加边费用流)

    参考题解:http://blog.csdn.net/yxuanwkeith/article/details/52254602

    //开始跑费用流用的dijkstra,一直错,后来发现动态加边后我不会处理势函数;
    //因为加进一些边后1号点到某个点的最短路不好更新,有些点是有势函数的,有些没有,图不平衡了;
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=100010;
    int head,tail,q[maxn],H[maxn],last[maxn],inf,All,S,T,n,m,Min,t[50][1000],vis[maxn],dis[maxn],in[maxn],p[50],cnt;
    struct edg{
        int nxt,to,f,c;
    }e[maxn*2];
    void insert(int x,int y,int z,int zz){
        ++cnt;e[cnt].nxt=last[x];last[x]=cnt;e[cnt].to=y;e[cnt].f=z;e[cnt].c=zz;
    }
    void add(int x,int k){
        //加第x个厨师的第k组边
        int u=(x-1)*All+k;
        if(k>All||vis[u])return;
        vis[u]=1;
        insert(S,u,1,0);insert(u,S,0,0);
        for(int i=1;i<=n;++i)
        {insert(u,All*m+i,1,t[i][x]*k);insert(All*m+i,u,0,-t[i][x]*k);}
    }
    int dfs(int x,int h){
        if(x==T){Min+=dis[T]*h;return h;}
        int tmp=0,cp;in[x]=1;
        for(int i=last[x];i;i=e[i].nxt){
            int v=e[i].to;
            if(dis[v]==dis[x]+e[i].c&&e[i].f&&!in[v]){
                cp=dfs(v,min(h-tmp,e[i].f));
                e[i].f-=cp;e[i^1].f+=cp;tmp+=cp;
                if(tmp==h){//动态加边:当前点跑满流了就新加边;
                    //注意加边的顺序,先加费用小的;
                    if(x<=All*m&&x!=S)add((x-1)/All+1,(x-1)%All+2);
                    return tmp;
                }
            }
        }
        return tmp;
    }
    void solve(){
        while(1){
            memset(in,0,sizeof(in));memset(dis,60,sizeof(dis));
            inf=dis[0];dis[S]=0;head=tail=0;
            q[++tail]=S;
            while(head!=tail){
                head=(head+1)%maxn;
                int u=q[head];
                for(int i=last[u];i;i=e[i].nxt){
                    int v=e[i].to;
                    if(e[i].f&&dis[v]>dis[u]+e[i].c){
                        dis[v]=dis[u]+e[i].c;
                        if(!in[v]){
                            in[v]=1;tail=(tail+1)%maxn;
                            q[tail]=v;
                        }
                    }
                }
                in[u]=0;
            }
            if(dis[T]==inf)return;
            dfs(S,inf);
        }
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;++i){
            scanf("%d",&p[i]);All+=p[i];
        }
        S=0,T=m*All+n+1;
        cnt=1;
        for(int i=1;i<=n;++i){
            insert(All*m+i,T,p[i],0);
            insert(T,All*m+i,0,0);
            for(int j=1;j<=m;++j)scanf("%d",&t[i][j]);
        }
        for(int i=1;i<=m;++i)add(i,1);
        solve();
        cout<<Min;
        system("pause");
        return 0;
    }
  • 相关阅读:
    WSS 扩展文件夹的属性如何给文件夹添加扩展字段
    SharePoint 打开文档附件不弹出提示框
    SharePoint2010 安装时报“未能启动数据库服务 MSSQL$Sharepoint"解决办法
    常见问题
    sharepoint 关于pdf格式在线打开
    ASP.NET 2.0 连接Sql Server 2005报错 [DBNETLIB][ConnectionOpen (Invalid Instance()).]无效的连线。
    <转>SQL Server 2008 R2十大新特性解析
    windows查看端口占用情况
    SQL Server适用脚本收集一
    信息系统中用户的域AD认证功能
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8270542.html
Copyright © 2011-2022 走看看