• luogu2891 [USACO07OPEN]吃饭Dining


    题目大意:

    有F种食物和D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料。现在有n头牛,每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享用到自己喜欢的食物和饮料。

    解题方法:

    这题算是网络流入门题,主要考如何构图,将食物置于左侧,牛置于中间,饮料置于右侧,依次连边,这样会发现无法满足每头牛只享用最多一种食物和一种饮料的条件。

    所以可将中间的每个牛拆成两个点,两点之间连一条流量为1的边,最后源点向所有食物连流量为1的边,所以饮料向汇点连流量为1的边,跑网络流即可。

    代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<cstdlib>
      6 #include<algorithm>
      7 #include<queue>
      8 using namespace std;
      9 const int MAXN=11000;
     10 const int INF=0x7fffffff;
     11 struct Edge
     12 {
     13     int v,c,next;
     14 }ed[MAXN*20];
     15 int n,f,d;
     16 int dis[MAXN];
     17 int nume=-1,head[MAXN]={0},cru[MAXN]={0};
     18 void add_edge(int u,int v,int c)
     19 {
     20     nume++;
     21     ed[nume].v=v;
     22     ed[nume].c=c;
     23     ed[nume].next=head[u];
     24     head[u]=nume;
     25     nume++;
     26     ed[nume].v=u;
     27     ed[nume].c=0;
     28     ed[nume].next=head[v];
     29     head[v]=nume;
     30 }
     31 bool BFS(int s,int t)
     32 {
     33     queue<int> team;
     34     team.push(s);
     35     memset(dis,0,sizeof(dis));
     36     dis[s]=1;
     37     while(!team.empty())
     38     {
     39         int u=team.front();
     40         team.pop();
     41         for(int i=head[u];i+1;i=ed[i].next)
     42         if(!dis[ed[i].v] && ed[i].c>0)
     43         {
     44             dis[ed[i].v]=dis[u]+1;
     45             team.push(ed[i].v);
     46         }
     47     }
     48     return dis[t];
     49 }
     50 int DFS(int now,int t,int flow)
     51 {
     52     if(now==t) return flow;
     53     int s=0,k;
     54     for(int &i=cru[now];i+1;i=ed[i].next)
     55     {
     56         int to=ed[i].v;
     57         if(ed[i].c>0 && dis[to]==dis[now]+1)
     58         {
     59             k=DFS(to,t,min(flow-s,ed[i].c));
     60             s+=k;
     61             ed[i].c-=k;ed[i^1].c+=k;
     62             if(s==flow) break;
     63         }
     64     }
     65     if(s==0) dis[now]=0;
     66     return s;
     67 }
     68 int Dinic(int s,int t)
     69 {
     70     int ans=0;
     71     while(BFS(s,t))
     72     {
     73         memcpy(cru,head,sizeof(head));
     74         ans+=DFS(s,t,INF);
     75     }
     76     return ans; 
     77 }
     78 int main()
     79 {
     80     int s,t;
     81     scanf("%d%d%d",&n,&f,&d);
     82     s=0;t=n*2+f+d;
     83     memset(head,-1,sizeof(head));
     84     for(int i=1;i<=f;i++) add_edge(s,i,1);
     85     for(int i=1;i<=n;i++) add_edge(f+i,f+i+n,1);
     86     for(int i=1;i<=d;i++) add_edge(2*n+f+i,t,1);
     87     for(int i=1;i<=n;i++)
     88     {
     89         int numf,numd;
     90         scanf("%d%d",&numf,&numd);
     91         int x;
     92         for(int j=1;j<=numf;j++)
     93         {
     94             scanf("%d",&x);
     95             add_edge(x,i+f,1);
     96         }
     97         for(int j=1;j<=numd;j++)
     98         {
     99             scanf("%d",&x);
    100             add_edge(n+i+f,2*n+f+x,1);
    101         }
    102     }
    103     printf("%d",Dinic(s,t));
    104     return 0;
    105 }
    View Code
  • 相关阅读:
    WinForm被遮挡的控件解决方案
    IC卡资料
    水晶报表2008部署
    打造最强的VC6
    SqlServer Case
    using namespace std
    非接触式IC智能(射频)卡
    删除VS2005插件

    SQLServer2005数据库自动备份
  • 原文地址:https://www.cnblogs.com/Oracle-LinJH/p/9820416.html
Copyright © 2020-2023  润新知