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 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    typedef vector VI;
    typedef vector VVI;
    typedef long long L;
    typedef vector VL;
    typedef vector VVL;
    typedef pair PII;
    typedef vector VPII;
    typedef vector VD;
    typedef vector 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 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 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 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 adj[maxn],nu;
    vector::iterator pre[maxn];
    queue 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::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::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

    poj2516

    最大流最小费模板

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    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 adj[maxn],nu;
    vector::iterator pre[maxn];
    queue 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::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::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;ist[i]){
                    ok=0;
                    break;
                }
            }
            if(!ok){
                printf("-1\n");
                continue;
            }
            int ans=0;
            for(i=0;i

    poj2226

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

    #include
    #include
    #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;j0 && map[i][j-1]=='*') ++cntr;
            }
        }
        for(j=0;j0 && map[i-1][j]=='*') ++cntc;
            }
        }
    
        for(i=0;i

    poj2391

    floyd+离散化+二分+dinic

    #include
    #include
    #include
    #include
    #include
    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 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>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;
    }


你可能感兴趣的:(练题总结)