如何建图?
最开始的问题就是,怎么表示一只牛有了食物和饮料呢?
后来发现可以先将食物与牛匹配,牛再去和饮料匹配,实际上这就构成了三个层次。
起点到食物层边的容量是1,食物层到奶牛层容量是1,奶牛层到饮料层容量是1,饮料层到终点容量是1。
但是后来发现有一组hack数据:
2 3 3
3 3 1 2 3 1 2 3
3 3 1 2 3 1 2 3
我们发现一头奶牛居然吃了多个套餐,所以要解决这个只需要将自己与自己建立一条容量是1的边就行了。
#include <cstdio> #include <cstring> #include <stack> using namespace std; #define sc scanf #define pt printf #define maxe 40960 #define maxv 405 #define maxn 1000 #define mll long long const int inf = 0x3f3f3f3f; int mn(int a,int b) { return a<b?a:b; } int s,t, N,F,D; typedef struct ed{ int v,w,cap,flow; } ed; ed e[maxe]; int head[maxv],nxt[maxe],tot,dis[maxv]; void init() { tot = 0 ; memset(head,-1,sizeof(head)); } void add(int u,int v,int cap,int flow) { e[tot].v=v; e[tot].cap=cap; e[tot].flow=flow; nxt[tot]=head[u]; head[u]=tot++; e[tot].v=u; e[tot].cap=flow; e[tot].flow=0; nxt[tot]=head[v]; head[v]=tot++; } int dfs(int u,int exp) { if(exp==0||u==t) return exp; int i,v,flow=0,tmp; for(i=head[u];i!=-1;i=nxt[i]) { v=e[i].v; //pt("u=%d,v=%d\n",u,v); if(dis[v]==dis[u]+1) { tmp = dfs(v,mn(e[i].cap-e[i].flow,exp)); if(tmp==0) continue; // pt("u=%d,v=%d,tmp=%d\n",u,v,tmp); e[i].flow += tmp; e[i^1].flow -= tmp; exp-=tmp; flow+=tmp; if(exp==0) break; } } //pt("wt\n"); if(flow==0) dis[u]=inf; return flow; } stack<int> q; int main() { freopen("in.txt","r",stdin); while(~sc("%d%d%d",&N,&F,&D)) { //pt("OK\n"); int i,j,ans=0,u,v,tt,FF,DD; init(); s=0,t=1+2*N+F+D; // pt("OK\n"); // F使用1-F N使用(F+1 - F+N)(F+1 + N - F+ 2*N) D使用 F+2*N+1 - F+2*N+D for(i=1;i<=F;++i) add(0,i,1,0); for(i=F+2*N+1;i<=F+2*N+D;++i) add(i,t,1,0); for(i=F+1;i<=F+N;++i) add(i,i+N,1,0); //pt("OK\n"); for(i=1;i<=N;++i) { sc("%d%d",&FF,&DD); for(j=1;j<=FF;++j) { sc("%d",&tt); add(tt,F+i,1,0); } for(j=1;j<=DD;++j) { sc("%d",&tt); add(F+N+i,F+2*N+tt,1,0); } } //pt("OK\n"); while(1) { //BFS建立层次图 memset(dis,inf,sizeof(dis)); dis[s]=0; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()) { u=q.top(); q.pop(); for(i=head[u];i!=-1;i=nxt[i]) { if(e[i].cap - e[i].flow <= 0) continue; v = e[i].v; if(dis[u]+1<dis[v]) { dis[v] = dis[u] +1; //pt("BFS: u=%d,v=%d\n",u,v); if(v==t) break; q.push(v); } } } if(dis[t]==inf) break; //DFS进行增广 tt=dfs(0,inf); if(tt==0) break; else ans+=tt; //pt("tt=%d\n",tt); } pt("%d\n",ans); } return 0; }
POJ 3281
原文地址:https://www.cnblogs.com/lighten-up-belief/p/11332102.html
时间: 2024-10-08 20:17:23