Assignment 8: Network Flow Problems

来源:互联网 发布:云计算是什么工作 编辑:程序博客网 时间:2024/05/21 19:49
  • 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 210struct 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 110int 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 1300int 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 0x3f3f3f3fstruct 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;}


原创粉丝点击