Assignment 8: Network Flow Problems

  • 1273 Drainage Ditches (1)

  • 1274 The Perfect Stall (1)

  • 2112 Optimal Milking (4)

  • 3041 Asteroids (5)

  • 3308 Paratroopers (6)

  • 2195 Going Home (6)

  • 2516 Minimum Cost (7)

  • 2455 Secret Milking Machine (7)

  • 2226 Muddy Fields (7)

  • 3281 Dining (7)

  • 2391 Ombrophobic Bovines (8, challenge problem)

  • 3498 March of the Penguins (8, challenge problem)


    poj2195

    最小费用二分图匹配的三种方式

    #include <cmath>
    #include <vector>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    typedef vector<int> VI;
    typedef vector<VI> VVI;
    typedef long long L;
    typedef vector<L> VL;
    typedef vector<VL> VVL;
    typedef pair<int, int> PII;
    typedef vector<PII> VPII;
    typedef vector<double> VD;
    typedef vector<VD> VVD;
    const L INF = 0x3f3f3f3f;
    
    struct MinCostMaxFlow {
    	int N;
    	VVL cap, flow, cost;
    	VI found;
    	VL dist, pi, width;
    	VPII dad;
    
    	MinCostMaxFlow(int N) :
    	N(N), cap(N, VL(N)), flow(N, VL(N)), cost(N, VL(N)),
    	found(N), dist(N), pi(N), width(N), dad(N) {}
    
    	void AddEdge(int from, int to, L cap, L cost) {
    		this->cap[from][to] = cap;
    		this->cost[from][to] = cost;
    	}
    
    	void Relax(int s, int k, L cap, L cost, int dir) {
    		L val = dist[s] + pi[s] - pi[k] + cost;
    		if (cap && val < dist[k]) {
    			dist[k] = val;
    			dad[k] = make_pair(s, dir);
    			width[k] = min(cap, width[s]);
    		}
    	}
    
    	L Dijkstra(int s, int t) {
    		fill(found.begin(), found.end(), false);
    		fill(dist.begin(), dist.end(), INF);
    		fill(width.begin(), width.end(), 0);
    		dist[s] = 0;
    		width[s] = INF;
    
    		while (s != -1) {
    			int best = -1;
    			found[s] = true;
    			for (int k = 0; k < N; k++) {
    				if (found[k]) continue;
    				Relax(s, k, cap[s][k] - flow[s][k], cost[s][k], 1);
    				Relax(s, k, flow[k][s], -cost[k][s], -1);
    				if (best == -1 || dist[k] < dist[best]) best = k;
    			}
    			s = best;
    		}
    
    		for (int k = 0; k < N; k++)
    		pi[k] = min(pi[k] + dist[k], INF);
    		return width[t];
    	}
    
    	pair<L, L> GetMaxFlow(int s, int t) {
    		L totflow = 0, totcost = 0;
    		while (L amt = Dijkstra(s, t)) {
    			totflow += amt;
    			for (int x = t; x != s; x = dad[x].first) {
    				if (dad[x].second == 1) {
    					flow[dad[x].first][x] += amt;
    					totcost += amt * cost[dad[x].first][x];
    				} else {
    					flow[x][dad[x].first] -= amt;
    					totcost -= amt * cost[x][dad[x].first];
    				}
    			}
    		}
    		return make_pair(totflow, totcost);
    	}
    };
    
    int ht,mt;
    char mat[110][110];
    typedef pair<int,int> pii;
    pii house[110],man[110];
    int dis(int i,int j){
        return abs(house[i].first-man[j].first)+abs(house[i].second-man[j].second);
    }
    void gao_mcmf(){
            MinCostMaxFlow my(ht+ht+2);
            for(int i=0;i<ht;++i){
                my.AddEdge(0,i+1,1,0);
                my.AddEdge(i+ht+1,ht+ht+1,1,0);
                for(int j=0;j<ht;++j){
                    my.AddEdge(i+1,ht+j+1,1,dis(i,j));
                }
            }
            printf("%lld\n",my.GetMaxFlow(0,ht+ht+1).second);
    }
    //
    double MinCostMatching(const VVD &cost, VI &Lmate, VI &Rmate) {
      int n = int(cost.size());
    
      // construct dual feasible solution
      VD u(n);
      VD v(n);
      for (int i = 0; i < n; i++) {
        u[i] = cost[i][0];
        for (int j = 1; j < n; j++) u[i] = min(u[i], cost[i][j]);
      }
      for (int j = 0; j < n; j++) {
        v[j] = cost[0][j] - u[0];
        for (int i = 1; i < n; i++) v[j] = min(v[j], cost[i][j] - u[i]);
      }
    
      // construct primal solution satisfying complementary slackness
      Lmate = VI(n, -1);
      Rmate = VI(n, -1);
      int mated = 0;
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          if (Rmate[j] != -1) continue;
          if (fabs(cost[i][j] - u[i] - v[j]) < 1e-10) {
    	Lmate[i] = j;
    	Rmate[j] = i;
    	mated++;
    	break;
          }
        }
      }
    
      VD dist(n);
      VI dad(n);
      VI seen(n);
    
      // repeat until primal solution is feasible
      while (mated < n) {
    
        // find an unmatched left node
        int s = 0;
        while (Lmate[s] != -1) s++;
    
        // initialize Dijkstra
        fill(dad.begin(), dad.end(), -1);
        fill(seen.begin(), seen.end(), 0);
        for (int k = 0; k < n; k++)
          dist[k] = cost[s][k] - u[s] - v[k];
    
        int j = 0;
        while (true) {
    
          // find closest
          j = -1;
          for (int k = 0; k < n; k++) {
    	if (seen[k]) continue;
    	if (j == -1 || dist[k] < dist[j]) j = k;
          }
          seen[j] = 1;
    
          // termination condition
          if (Rmate[j] == -1) break;
    
          // relax neighbors
          const int i = Rmate[j];
          for (int k = 0; k < n; k++) {
    	if (seen[k]) continue;
    	const double new_dist = dist[j] + cost[i][k] - u[i] - v[k];
    	if (dist[k] > new_dist) {
    	  dist[k] = new_dist;
    	  dad[k] = j;
    	}
          }
        }
    
        // update dual variables
        for (int k = 0; k < n; k++) {
          if (k == j || !seen[k]) continue;
          const int i = Rmate[k];
          v[k] += dist[k] - dist[j];
          u[i] -= dist[k] - dist[j];
        }
        u[s] += dist[j];
    
        // augment along path
        while (dad[j] >= 0) {
          const int d = dad[j];
          Rmate[j] = Rmate[d];
          Lmate[Rmate[j]] = j;
          j = d;
        }
        Rmate[j] = s;
        Lmate[s] = j;
    
        mated++;
      }
    
      double value = 0;
      for (int i = 0; i < n; i++)
        value += cost[i][Lmate[i]];
    
      return value;
    }
    VI Lmate,Rmate;
    void gao_mcmatch(){
        VD temp(ht,0);
        VVD cost(ht,temp);
            for(int i=0;i<ht;++i){
                for(int j=0;j<ht;++j){
                    cost[i][j]=dis(i,j);
                }
            }
        printf("%.0f\n",MinCostMatching(cost,Lmate,Rmate));
    }
    
    #define maxn 210
    struct NODE{
        NODE(){}
        NODE(int uu,int vv,int cc,int ww,int pp):u(uu),v(vv),c(cc),w(ww),p(pp){}
        int u,v,c,w,p;
    };
    vector<NODE> adj[maxn],nu;
    vector<NODE>::iterator pre[maxn];
    queue<int> q;
    int cnt[maxn];
    int d[maxn];
    bool vis[maxn];
    void add(int u,int v,int c,int w){
        adj[u].push_back(NODE(u,v,c,w,adj[v].size()));
        adj[v].push_back(NODE(v,u,0,-w,adj[u].size()-1));
    }
    int n;
    int spfa(){
        while(!q.empty()) q.pop();
        fill(d,d+n+2,INF);
        memset(cnt,0,sizeof(cnt));
        memset(vis,0,sizeof(vis));
        d[0]=0;
        cnt[0]=1;
        vis[0]=1;
        pre[0]=nu.begin();
        q.push(0);
        int u,v,c;
        vector<NODE>::iterator it;
        while(!q.empty()){
            u=q.front();
            q.pop();
            vis[u]=0;
            for(it=adj[u].begin();it!=adj[u].end();++it){
                v=it->v;
                if(it->c && d[v]>d[u]+it->w){
                    d[v]=d[u]+it->w;
                    pre[v]=it;
                    if(!vis[v]){
                        if(++cnt[v]>n+1) return 0;
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        if(d[n+1]==INF) return 0;
        return 1;
    }
    int mfmc(){
        int ans=0,m;
        vector<NODE>::iterator it;
        while(spfa()){
            m=INF;
            for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){
                m=min(m,it->c);
            }
            for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){
                it->c-=m;
                adj[it->v][it->p].c+=m;
            }
            ans+=m*d[n+1];
        }
        return ans;
    }
    void gao_mfmc(){
        int i,j;
        n=ht+ht;
        for(i=0;i<=n+1;++i) adj[i].clear();
            for(int i=0;i<ht;++i){
                add(0,i+1,1,0);
                add(i+ht+1,n+1,1,0);
                for(int j=0;j<ht;++j){
                    add(i+1,ht+j+1,1,dis(i,j));
                }
            }
        printf("%d\n",mfmc());
    }
    ///
    int main(){
        int m,n,i,j;
        while(scanf("%d%d",&m,&n)!=EOF && m){
            ht=mt=0;
            for(i=0;i<m;++i){
                scanf("%s",mat[i]);
                for(j=0;j<n;++j){
                    if(mat[i][j]=='H') {
                        house[ht].first=i,house[ht].second=j;
                        ++ht;
                    }else if(mat[i][j]=='m'){
                        man[mt].first=i,man[mt].second=j;
                        ++mt;
                    }
                }
            }
          //  gao_mcmf();
          //  gao_mcmatch();
          gao_mfmc();
        }
        return 0;
    }

    poj2516

    最大流最小费模板

    #include <cmath>
    #include <vector>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    #define INF 0x3f3f3f3f
    #define maxn 110
    int cost[55][55][55];
    int buy[55][55],sell[55][55],bt[55],st[55];
    struct NODE{
        NODE(){}
        NODE(int uu,int vv,int cc,int ww,int pp):u(uu),v(vv),c(cc),w(ww),p(pp){}
        int u,v,c,w,p;
    };
    vector<NODE> adj[maxn],nu;
    vector<NODE>::iterator pre[maxn];
    queue<int> q;
    int cnt[maxn];
    int d[maxn];
    bool vis[maxn];
    void add(int u,int v,int c,int w){
        adj[u].push_back(NODE(u,v,c,w,adj[v].size()));
        adj[v].push_back(NODE(v,u,0,-w,adj[u].size()-1));
    }
    int n,B,S,K;
    int spfa(){
        while(!q.empty()) q.pop();
        fill(d,d+n+2,INF);
        memset(cnt,0,sizeof(cnt));
        memset(vis,0,sizeof(vis));
        d[0]=0;
        cnt[0]=1;
        vis[0]=1;
        pre[0]=nu.begin();
        q.push(0);
        int u,v,c;
        vector<NODE>::iterator it;
        while(!q.empty()){
            u=q.front();
            q.pop();
            vis[u]=0;
            for(it=adj[u].begin();it!=adj[u].end();++it){
                v=it->v;
                if(it->c && d[v]>d[u]+it->w){
                    d[v]=d[u]+it->w;
                    pre[v]=it;
                    if(!vis[v]){
                        if(++cnt[v]>n+1) return 0;
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        if(d[n+1]==INF) return 0;
        return 1;
    }
    int mfmc(){
        int ans=0,m;
        vector<NODE>::iterator it;
        while(spfa()){
            m=INF;
            for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){
                m=min(m,it->c);
            }
            for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){
                it->c-=m;
                adj[it->v][it->p].c+=m;
            }
            ans+=m*d[n+1];
        }
        return ans;
    }
    int gao_mfmc(int k){
        int i,j;
        for(i=0;i<=n+1;++i) adj[i].clear();
        for(i=0;i<S;++i){
            add(0,i+1,sell[k][i],0);
        }
        for(i=0;i<B;++i){
            add(i+S+1,n+1,buy[k][i],0);
        }
        for(i=0;i<B;++i){
            for(j=0;j<S;++j){
                add(j+1,i+S+1,INF,cost[k][i][j]);
            }
        }
        return mfmc();
    }
    int main(){
        int i,j,k;
        while(scanf("%d%d%d",&B,&S,&K)!=EOF && B){
            n=B+S;
            memset(bt,0,sizeof(bt));
            memset(st,0,sizeof(st));
            for(i=0;i<B;++i){
                for(j=0;j<K;++j){
                    scanf("%d",&buy[j][i]);
                    bt[j]+=buy[j][i];
                }
            }
            for(i=0;i<S;++i){
                for(j=0;j<K;++j){
                    scanf("%d",&sell[j][i]);
                    st[j]+=sell[j][i];
                }
            }
            for(k=0;k<K;++k){
                for(i=0;i<B;++i){
                    for(j=0;j<S;++j){
                        scanf("%d",&cost[k][i][j]);
                    }
                }
            }
            int ok=1;
            for(i=0;i<K;++i){
                if(bt[i]>st[i]){
                    ok=0;
                    break;
                }
            }
            if(!ok){
                printf("-1\n");
                continue;
            }
            int ans=0;
            for(i=0;i<K;++i){
                ans+=gao_mfmc(i);
            }
            printf("%d\n",ans);
        }
        return 0;
    }

    poj2226

    以连续线段为结点,最大二分匹配(匈牙利算法)

    #include<cstdio>
    #include<cstring>
    #define maxn 1300
    int mat[maxn][maxn],match[maxn];
    bool vis[maxn];
    char map[55][55];
    int r[55][55],c[55][55];
    int cntr,cntc;
    int m,n;
    bool dfs(int i){
        int j;
        for(j=0;j<cntc;++j){
            if(!mat[i][j] || vis[j]) continue;
            vis[j]=1;
            if(match[j]==-1 || dfs(match[j])){
                match[j]=i;
                return 1;
            }
        }
        return 0;
    }
    int main(){
       // freopen("d.in","r",stdin);
        int i,j,ans=0;
        memset(match,-1,sizeof(match));
        scanf("%d%d",&m,&n);
        for(i=0;i<m;++i){
            scanf("%s",map[i]);
            map[i][n]='.';
        }
        for(i=0;i<n;++i) map[m][i]='.';
        for(i=0;i<m;++i){
            for(j=0;j<=n;++j){
                if(map[i][j]=='*') r[i][j]=cntr;
                else if(j>0 && map[i][j-1]=='*') ++cntr;
            }
        }
        for(j=0;j<n;++j){
            for(i=0;i<=m;++i){
                if(map[i][j]=='*') c[i][j]=cntc;
                else if(i>0 && map[i-1][j]=='*') ++cntc;
            }
        }
    
        for(i=0;i<m;++i){
            for(j=0;j<n;++j){
                if(map[i][j]=='*'){
                    mat[r[i][j]][c[i][j]]=1;
                }
            }
        }
        for(i=0;i<cntr;++i){
            memset(vis,0,sizeof(vis));
            if(dfs(i)) ++ans;
        }
        printf("%d\n",ans);
        return 0;
    }

    poj2391

    floyd+离散化+二分+dinic

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long u64;
    typedef int type;
    #define maxn 205
    #define maxm 81205
    #define INF 0x3ffffffffffffLL
    #define inf 0x3f3f3f3f
    struct EDGE{
        int v,next;
        type c;
    }edge[maxm];
    u64 mat[maxn][maxn];
    int n,N,M;
    int have[maxn],hold[maxn];
    int d[maxn<<1],head[maxn<<1];
    int src,des,tot,all;
    void init(){
        memset(head,-1,sizeof(head));
        tot=0;
    }
    void add(int u,int v,type c){
        edge[tot].v=v,edge[tot].c=c,edge[tot].next=head[u];head[u]=tot++;
        edge[tot].v=u,edge[tot].c=0,edge[tot].next=head[v];head[v]=tot++;
    }
    queue<int> q;
    bool bfs(){
        while(!q.empty()) q.pop();
        int u,v,i;
        type c;
        memset(d,-1,sizeof(d));
        d[src]=0;
        q.push(src);
        while(!q.empty()){
            u=q.front();
            q.pop();
            for(i=head[u];i!=-1;i=edge[i].next){
                v=edge[i].v;
                c=edge[i].c;
                if(c>0 && d[v]==-1){
                    d[v]=d[u]+1;
                    q.push(v);
                }
            }
        }
        return (d[des]!=-1);
    }
    type dfs(int u,type mm){
        if(u==des) return mm;
        int i,v;
        type c,temp;
        for(i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].v;
            c=edge[i].c;
            if(c>0 && d[v]==d[u]+1 && (temp=dfs(v,min(mm,c)))){
                edge[i].c-=temp;
                edge[i^1].c+=temp;
                return temp;
            }
        }
        d[u]=-1;
        return 0;
    }
    type dinic(){
        type ans=0,temp;
        while(bfs()){
            while(1){
                temp=dfs(src,inf);
                if(!temp) break;
                ans+=temp;
            }
        }
        return ans;
    }
    bool check(u64 k){
        int i,j;
        init();
        for(i=1;i<=N;++i){
            for(j=1;j<=N;++j){
                if(mat[i][j]<=k && i!=j && have[i]){
                    add(i,j+N,have[i]);
                }
            }
            if(have[i]){
                add(i,N+i,have[i]);
                add(src,i,have[i]);
            }
            if(hold[i]){
                add(i+N,des,hold[i]);
            }
        }
        if(dinic()==all) return 1;
        return 0;
    }
    u64 h[maxn*maxn];
    int cnt;
    int main(){
       //freopen("data.in","r",stdin);//freopen("data.out","w",stdout);
        int i,j,u,v,k,l,r,m;
        u64 c;
        scanf("%d%d",&N,&M);
        for(i=1;i<=N;++i){
            scanf("%d%d",&have[i],&hold[i]);
            all+=have[i];
            for(j=1;j<=N;++j) mat[i][j]=INF;
        }
        while(M--){
            scanf("%d%d%lld",&u,&v,&c);
            mat[u][v]=min(mat[u][v],c);
            mat[v][u]=min(mat[v][u],c);
        }
        for(k=1;k<=N;++k){
            for(i=1;i<=N;++i){
                for(j=1;j<=N;++j){
                    mat[i][j]=min(mat[i][j],mat[i][k]+mat[k][j]);
                }
            }
        }
        cnt=1;
        for(i=1;i<=N;++i){
            for(j=i+1;j<=N;++j){
                if(mat[i][j]!=INF){
                    h[cnt++]=mat[i][j];
                }
            }
        }
        n=N+N+2;
        src=0,des=n-1;
        sort(h,h+cnt);
        cnt=unique(h,h+cnt)-h;
        l=0,r=cnt-1;
        if(!check(h[r])){
            printf("-1\n");
            return 0;
        }
        while(l+1<r){
            m=(l+r)>>1;
          // printf("l=%d r=%d h[m]=%lld\n",l,r,h[m]);
            if(check(h[m])) r=m;
            else l=m;
        }
        printf("%lld\n",h[r]);
        return 0;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值