题目: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! "); else printf("I'd rather not wear a shirt anyway... "); } return 0; }