POJ 2391 二分+SAP最大流

来源:互联网 发布:php mysql 三表联查 编辑:程序博客网 时间:2024/05/01 07:11
#include<cstdio>#include<cstring>#include<iostream>#include<iomanip>#include<queue>#include<cmath>#include<stack>#include<map>#include<vector>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int int_max = 0x07777777;const int int_min = 0x80000000;const int maxn = 500;struct Edge{    int from, to, cap, flow;    Edge(int _from, int _to, int _cap, int _flow):from(_from),to(_to),cap(_cap),flow(_flow){}};vector<Edge> es;vector<int> g[maxn];int s,t;int p[maxn],d[maxn],gap[maxn],cur[maxn];void addedge (int from, int to, int cap){    es.push_back(Edge(from, to, cap, 0));    es.push_back(Edge(to, from, 0,0));    int num = es.size();    g[from].push_back(num-2);    g[to].push_back(num-1);}void BFS (){    queue<int> q;    memset(d, 0, sizeof(d));    d[t] = 0;    q.push(t);    while(!q.empty()){        int u = q.front();        q.pop();        for(int i = 0; i < g[u].size(); i++){            Edge& e = es[g[u][i]];            if(g[u][i]&1 && d[e.to]==0){                d[e.to] = d[u]+1;                q.push(e.to);            }        }    }}int augment (){    int x = t;    int a = int_max;    while(x!=s){        Edge& e = es[p[x]];        a = (a < e.cap-e.flow ? a : e.cap-e.flow);        x = es[p[x]].from;    }    x = t;    while(x!=s){        es[p[x]].flow += a;        es[p[x]^1].flow -= a;        x = es[p[x]].from;    }    return a;}int sap (){    int flow = 0;    BFS();    memset(gap, 0, sizeof(gap));    for(int i = 1; i <= t; i++) gap[d[i]]++;    int x = s;    memset(cur, 0, sizeof(cur));    while(d[s] < t+1){        if(x==t){            flow += augment();            x = s;        }        int ok = 0;        for(int i = 0; i < g[x].size(); i++){            Edge& e = es[g[x][i]];            if(e.cap > e.flow && d[x]==d[e.to]+1){                ok = 1;                p[e.to] = g[x][i];                cur[x] = i;                x = e.to;                break;            }        }        if(!ok){            int mm = t;            for(int i = 0; i < g[x].size(); i++){                Edge& e = es[g[x][i]];                if(e.cap > e.flow) mm = (mm > d[e.to] ? d[e.to] : mm);            }            if(--gap[d[x]] == 0) break;            gap[d[x]=mm+1]++;            cur[x] = 0;            if(x!=s) x = es[p[x]].from;        }    }    return flow;}int cow[maxn],shelter[maxn];int mysum;long long mymap[maxn][maxn];int main(int argc, const char * argv[]){    int N, M;    while(scanf("%d %d", &N, &M)!=EOF){        mysum = 0;        for(int i = 1; i <= N; i++) {            scanf("%d %d", &cow[i], &shelter[i]);            mysum += cow[i];        }        for(int i = 1; i <= N; i++)            for(int j = 1; j <= N; j++) mymap[i][j] = (i==j ? 0 : -1);        long long maxlenth = -1;        for(int i = 0; i < M; i++){            int x,y;            long long z;            cin >> x >> y;            cin >> z;            if(mymap[x][y]==-1 || mymap[x][y]>z){                mymap[x][y] = z;                mymap[y][x] = z;                maxlenth = (maxlenth > z ? maxlenth : z);            }        }                for(int k = 1; k <= N; k++){            for(int i = 1; i <= N; i++){                for(int j = 1; j <= N; j++){                    if(mymap[i][k]==-1 || mymap[k][j]==-1) continue;                    if(mymap[i][j]==-1 || mymap[i][j] > mymap[i][k]+mymap[k][j]) {                        mymap[i][j] = mymap[i][k] + mymap[k][j];                        mymap[j][i] = mymap[i][j];                        maxlenth = (maxlenth < mymap[i][j] ? mymap[i][j] : maxlenth);                    }                }            }        }        long long l = 0;        long long r = maxlenth+1;        long long mid, result = -1;        while(l<=r){            mid = (l+r)/2;            es.clear();            for(int i = 0; i < maxn; i++) g[i].clear();            s = N*2+1;            t = s+1;            for(int i = 1; i <= N; i++){                addedge(s, i, cow[i]);                addedge(i, i+N, int_max);                addedge(i+N, t, shelter[i]);                for(int j = 1; j <= N; j++){                    if(j!=i && mymap[i][j]!=-1 && mymap[i][j]<=mid){                        addedge(i, j+N, int_max);                    }                }            }            if(sap()==mysum){                r = mid-1;                result = mid;            }else{                l = mid+1;            }        }        cout << result << endl;    }}

0 0
原创粉丝点击