poj 3436 网络流基础题

来源:互联网 发布:mysql root 权限不足 编辑:程序博客网 时间:2024/06/11 09:47
[题目链接](http://poj.org/problem?id=3436)题意: 题意确实难读。首先给出p,n 两个数 表示有p台机床来组装电脑,每台电脑有n个零件需要组装接着p行,每行描述一台机床 共2*n+1个数字,第一个数字表示每单位时间该机床能处理多少未完成品接下来n个数字表示该机床能接受的未完成品类型 0表示该零件不能存在 1表示该零件必须存在 2表示该零件可存在最后n个数字表示处理后 未完成品是什么样的。问怎么样用这些机床构成生产线 使得单位产量最大最后要你打印路径。写的第一道不是那么裸的网络流题目,因为要打印路径 所以不能直接套模板。 先按老套路,拆点建边。建好图之后,跑一遍网络流。 然后再遍历一遍原来的边,如果这条边有用的话,那他的流量肯定小于容量,把这些边全部找出来就行。 
#include<cmath>#include<cstring>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstdio>#define For(a,b,c) for(a=b;a<=c;a++)#include<queue>using namespace std;int n,m;int val[300];const int inf = 0x3f3f3f3f;const int MX=300 ;const int MXE= 4 * MX * MX;struct Edge {        int u,v, w, nxt;};struct MaxFlow {    Edge edge[MXE];    int tot, num, s, t;    int head[MX];    void init() {        memset(head, -1, sizeof(head));        tot = 0;    }    void add(int u, int v, int w) {        edge[tot].u = u;        edge[tot].v = v;        edge[tot].w = w;        edge[tot].nxt = head[u];        head[u] = tot++;        edge[tot].u = v;        edge[tot].v = u;        edge[tot].w = 0;        edge[tot].nxt = head[v];        head[v] = tot++;    }    int  d[MX], vis[MX], gap[MX];    void bfs() {        memset(d, 0, sizeof(d));        memset(gap, 0, sizeof(gap));        memset(vis, 0, sizeof(vis));        queue<int>q;        q.push(t);        vis[t] = 1;        while (!q.empty()) {            int u = q.front();            q.pop();            for (int i = head[u]; ~i; i = edge[i].nxt) {                int v = edge[i].v;                if (!vis[v]) {                    d[v] = d[u] + 1;                    gap[d[v]]++;                    q.push(v);                    vis[v] = 1;                }            }        }    }    int last[MX];    int dfs(int u, int f) {        if (u == t) return f;        int sap = 0;        for (int i = last[u]; ~i; i = edge[i].nxt) {            int v = edge[i].v;            if (edge[i].w > 0 && d[u] == d[v] + 1) {                last[u] = i;                int tmp = dfs(v, min(f - sap, edge[i].w));                edge[i].w -= tmp;                edge[i ^ 1].w += tmp;                sap += tmp;                if (sap == f) return sap;            }        }        if (d[s] >= num) return sap;        if (!(--gap[d[u]])) d[s] = num;        ++gap[++d[u]];        last[u] = head[u];        return sap;    }    int solve(int st, int ed, int n) {        int flow = 0;        num = n;        s = st;        t = ed;        bfs();        memcpy(last, head, sizeof(head));        while (d[s] < num) flow += dfs(s, inf);        return flow;    }    void slove(vector<Edge> &V) {        for(int i=0;i<tot;i+=2){            if(edge[i].u>m) continue;            if(edge[i].w<val[edge[i].u]){                Edge cnt;                int sum=val[edge[i].u]-edge[i].w;                for(int j=head[edge[i].u+m];j!=-1;j=edge[j].nxt){                    int v=edge[j].v;                    if(v==2*m+1) continue;// 连向超级汇点的边要跳过                    if(edge[j].w<20000) continue;// 反向边跳过                    cnt.u=edge[i].u;                    if(edge[j].w<inf){                        cnt.v=edge[j].v;                        cnt.w=inf-edge[j].w;                        V.push_back(cnt);                    }                }            }        }    }} F;int str[300][2][50];bool check1(int a[],int len) {    //for(int i=1; i<=len; i++)cout<<a[i]<<" ";    //puts("");    for(int i=1; i<=len; i++) {        if(a[i]==1) return false;    }    return true;}bool check2(int a[],int len) {    for(int i=1; i<=len; i++) {        if(a[i]!=1) return false;    }    return true;}bool cmp(int a[],int b[],int len) {    //for(int i=1; i<=len; i++)cout<<a[i]<<" ";    //puts("");    for(int i=1; i<=len; i++) {        if(((a[i]==1 && b[i]==0)||(a[i]==0 && b[i]==1))) return false;    }    return true;}int main() {    while(~scanf("%d %d",&n,&m)) {        F.init();        int cnt;        for(int i=1; i<=m; i++) {            scanf("%d",&val[i]);            for(int j=1; j<=n; j++) {                scanf("%d",&str[i][0][j]);            }            for(int j=1; j<=n; j++) {                scanf("%d",&str[i][1][j]);            }        }        // 建边        for(int i=1; i<=m; i++) {            if(check1(str[i][0],n)) {                F.add(0,i,inf);            }            if(check2(str[i][1],n)) {                F.add(i+m,2*m+1,inf);            }            F.add(i,i+m,val[i]);            for(int j=1; j<=m; j++) {                if(i==j) continue;                if(cmp(str[i][1],str[j][0],n)) {                    F.add(i+m,j,inf);                }            }        }        cout<<F.solve(0,2*m+1,2*m+2);        vector<Edge> ans;        F.slove(ans);        cout<<" "<<ans.size()<<endl;        for(int i=0;i<ans.size();i++){            printf("%d %d %d\n",ans[i].u,ans[i].v,ans[i].w);        }    }    return 0;}

原创粉丝点击