poj2584T-Shirt——网络最大流

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

以人和衣服作为点,建立超级源点和超级汇点,人连边权为1的边,衣服对源点连边权为件数的边(别弄乱顺序);

试图写构造函数,但CE了,最后只好用冗杂的写法。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>q;
int n,head[30],ct=1,d[30],cur[30],INF=1e9,s,t;
char dc[105];
struct N{
    int to,next,w;
}edge[705];
//struct N{
//    int next,to,w;
//    N(int a=0,int b=0,int c=0):next(a),to(b),w(c) {}
//}edge[255];
int ex(char cc)
{
    if(cc=='S')return 1;
    if(cc=='M')return 2;
    if(cc=='L')return 3;
    if(cc=='X')return 4;
    if(cc=='T')return 5;
}
void ad(int x,int y,int z)
{
//    edge[++ct]=(N){y,head[x],z};head[x]=ct;
//    edge[++ct]=(N){x,head[y],0};head[y]=ct;
    edge[++ct].to=y;
    edge[ct].next=head[x];
    edge[ct].w=z;
    head[x]=ct;
    edge[++ct].to=x;
    edge[ct].next=head[y];
    edge[ct].w=0;
    head[y]=ct;
//    edge[++ct]=N{y,head[x],z};head[x]=ct;
//    edge[++ct]=N{x,head[y],0};head[y]=ct;
}
void add(int p,char c[])
{
    int x=n+ex(c[0]);
    int y=n+ex(c[1]);
    for(int i=x;i<=y;i++)ad(i,p,1);
}
bool bfs()
{
    memset(d,0,sizeof d);
    while(q.size())q.pop();
    q.push(0);d[0]=1;
    while(q.size())
    {
        int x=q.front();q.pop();
        for(int i=head[x];i;i=edge[i].next)
        {
            int u=edge[i].to;
            if(!d[u]&&edge[i].w)
            {
                d[u]=d[x]+1;
                q.push(u);
            }
        }
    }
    return d[t];
}
int dfs(int x,int f)
{
    if(x==t)return f;
    int res=0;
    for(int i=cur[x];i;i=edge[i].next)
    {
        int u=edge[i].to;
        if(d[u]==d[x]+1&&edge[i].w)
        {
            int tmp=dfs(u,min(edge[i].w,f-res));
            edge[i].w-=tmp;
            edge[i^1].w+=tmp;
            res+=tmp;
            if(edge[i].w)cur[x]=i;
            if(res==f)return f;
        }
    }
    if(!res)d[x]=0;//剪枝 
    return res;
}
bool dinic()
{
    int ret=0;
    while(bfs())
    {
        for(int i=s;i<=t;i++)cur[i]=head[i];
        ret+=dfs(s,INF);
    }
    if(ret==n)return 1;
    else return 0;
}
int main()
{
    while(1)
    {
        cin>>dc;
        if(dc[0]=='E')return 0;
        ct=1;//!
        memset(head,0,sizeof head);
        scanf("%d ",&n);
        for(int i=1;i<=n;i++)
        {
            cin>>dc;
            add(i,dc);
        }
        for(int i=n+1;i<=n+5;i++)
        {
            int x;
            scanf("%d",&x);
            ad(0,i,x);//0为超级源点 
        }
        for(int i=1;i<=n;i++)ad(i,n+6,1);//n+6为超级汇点 
        s=0;t=n+6;
        cin>>dc;
        if(dinic())printf("T-shirts rock!\n");
        else printf("I'd rather not wear a shirt anyway...\n");
    }
    return 0;
}

 

posted @ 2018-03-19 23:54  Zinn  阅读(172)  评论(0编辑  收藏  举报