POJ-2584-T-Shirt Gumbo

来源:互联网 发布:华盛顿大学怎么样 知乎 编辑:程序博客网 时间:2024/06/06 09:58

POJ-2584-T-Shirt Gumbo

http://poj.org/problem?id=2584

最大流,源点向5种衣服建边,权值为该衣服的数量,衣服向人建边,权值为1,人向汇点建边,权值为1

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxn = 500;const int maxm = 500000;const int INF=1<<30;int idx;int cur[maxn], pre[maxn];int dis[maxn], gap[maxn];int aug[maxn], head[maxn];struct Node{int u, v, w;int next;}edge[maxm];int sol(char c){if(c=='S')return 1;if(c=='M')return 2;if(c=='L')return 3;if(c=='X')return 4;if(c=='T')return 5;}void addEdge(int u, int v, int w){    edge[idx].u = u;    edge[idx].v = v;    edge[idx].w = w;    edge[idx].next = head[u];head[u] = idx++;    edge[idx].u = v;    edge[idx].v = u;    edge[idx].w = 0;    edge[idx].next = head[v];    head[v] = idx++;}int SAP(int s, int e, int n){int max_flow = 0, v, u = s;    int id, mindis;    aug[s] =INF;    pre[s] = -1;    memset(dis, 0, sizeof(dis));    memset(gap, 0, sizeof(gap));    gap[0] = n; // 我觉得这一句要不要都行,因为dis[e]始终为0    for (int i = 0; i <= n; ++i)   // 初始化当前弧为第一条弧    cur[i] = head[i];    while (dis[s] < n)    {        bool flag = false;        if (u == e)        {            max_flow += aug[e];            for (v = pre[e]; v != -1; v = pre[v]) // 路径回溯更新残留网络            {                id = cur[v];                edge[id].w -= aug[e];                edge[id^1].w += aug[e];                aug[v] -= aug[e]; // 修改可增广量,以后会用到                if (edge[id].w == 0) u = v; // 不回退到源点,仅回退到容量为0的弧的弧尾            }        }        for (id = cur[u]; id != -1; id = edge[id].next)        {   // 从当前弧开始查找允许弧            v = edge[id].v;            if (edge[id].w > 0 && dis[u] == dis[v] + 1) // 找到允许弧            {                flag = true;                pre[v] = u;                cur[u] = id;                aug[v] = min(aug[u], edge[id].w);                u = v;                break;            }        }        if (flag == false)        {            if (--gap[dis[u]] == 0) break; /* gap优化,层次树出现断层则结束算法 */            mindis = n;            cur[u] = head[u];            for (id = head[u]; id != -1; id = edge[id].next)            {                v = edge[id].v;                if (edge[id].w > 0 && dis[v] < mindis)                {                    mindis = dis[v];                    cur[u] = id; // 修改标号的同时修改当前弧                }            }            dis[u] = mindis + 1;            gap[dis[u]]++;            if (u != s) u = pre[u]; // 回溯继续寻找允许弧        }    }    return max_flow;}int main(){char str[20];char ss[5000][2];int i,j,n,cur;int st,ed;int a,b;while(scanf("%s",str),strcmp(str,"ENDOFINPUT")){getchar();scanf("%d",&n);getchar();for(i=1;i<=n;i++)scanf("%s",ss[i]);st=0;ed=5+n+1;idx=0;memset(head,-1,sizeof(head));for(i=1;i<=5;i++){scanf("%d",&cur);addEdge(st,i,cur);}for(i=6;i<=5+n;i++){a=sol(ss[i-5][0]);b=sol(ss[i-5][1]);for(j=a;j<=b;j++)addEdge(j,i,1);addEdge(i,ed,1);}scanf("%s",str);if(SAP(st,ed,n+5+2)==n)printf("T-shirts rock!\n");elseprintf("I'd rather not wear a shirt anyway...\n");}return 0;}