poj 3281

来源:互联网 发布:淘宝联盟是骗局吗 编辑:程序博客网 时间:2024/06/15 06:12

题意:给出牛,饮料还有食物的数量,每头牛给出喜欢的饮料和食物,最后求出能够满足的牛的数量

一开始觉得是二分图匹配,但是怎么配两边的呢?
遂放弃。

然后 听说网络流可以弄二分图?

很好。怎么解决 一头牛对应一种呢?把牛拆成;两个点,中间连一条边权为1的边。

搞定。那现在说一下EK算法。

戳这里就好
给个模板题 1273

#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int VM=220;const int INF=0x3f3f3f3f;int n,m,max_flow;   //max_flow是最大流int map[VM][VM],flow[VM][VM];   // map[i][j]是每条边的容量,flow[i][j]是每条边的流量 int res[VM],pre[VM];    //res[]是每个点的剩余流量,pre[]是每个点的父亲int EK(int src,int des){    max_flow=0;    queue<int> q;    while(!q.empty())        q.pop();    memset(flow,0,sizeof(flow));    //最开始每条边的流量都是0    while(1){        memset(res,0,sizeof(res));  //残余流量得变0,一开始所有点都没流入对吧        res[src]=INF;   //源点嘛,剩余流量无限是必须的...        q.push(src);    //从源点开始进行BFS找增广路        int u,v;        while(!q.empty()){            u=q.front();            q.pop();            for(v=1;v<=m;v++)       //遍历所有点,找可行边                if(!res[v] && map[u][v]>flow[u][v]){    //该点剩余流量为0 且 容量大于流量,也就是找到了新的结点                     pre[v]=u;   //找到新结点,父节点得记录一下吧                    q.push(v);                    res[v]=min(res[u],map[u][v]-flow[u][v]);    //如果u的剩余流量能填满uv就填满,不能的话就把u这点的流量全部流向uv                 }        }        if(res[des]==0)     //如果当前已经是最大流,汇点没有残余流量            return max_flow;        for(u=des;u!=src;u=pre[u]){     //如果还能增广,那么回溯,从汇点往回更新每条走过的边的流量            flow[pre[u]][u]+=res[des];  //更新正向流量   (注意这里更新的是流量,而不是容量)            flow[u][pre[u]]-=res[des];  //更新反向流量           }        max_flow+=res[des];    }}int main(){    while(~scanf("%d%d",&n,&m)){        memset(map,0,sizeof(map));        memset(pre,0,sizeof(pre));        int u,v,w;        while(n--){            scanf("%d%d%d",&u,&v,&w);            map[u][v]+=w;   //有重边        }        printf("%d\n",EK(1,m));    }    return 0;}

所以这道题为什么WA了一次

因为 我没有建后向边,也就是凡是有一条正向的这样的边都要建一条反向的边权为0的边来退流!!!!

推流!!!不然时挂的!!
1.对算法本身并没有吃透
2.建边的技巧

#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#define inf 0x3fffffff//by mars_chusing namespace std;int n,f,d; struct data{    int f,t,nxt,c;}e[100005];int tot,first[605];int flow[605][605];int pre[605],res[605];void add(int a,int b,int c){    e[tot].f=a;    e[tot].t=b;    e[tot].c=c;    e[tot].nxt=first[a];    first[a]=tot++;}int EK(int s,int end){    queue<int> q;    int max_flow=0;    while(1)    {        memset(res,0,sizeof(res));        res[s]=inf;        q.push(s);        while(!q.empty())        {            int t=q.front();            q.pop();            for(int j=first[t];j!=-1;j=e[j].nxt)            {                int v=e[j].t;                if(!res[v] && e[j].c>flow[t][v])                {                    pre[v]=t;                    q.push(v);                    res[v]=min(res[t],e[j].c-flow[t][v]);                }            }        }        if(res[end] == 0)        {            return max_flow;        }        for(int i=end;i!=s;i=pre[i])        {            flow[pre[i]][i]+=res[end];            flow[i][pre[i]]-=res[end];        }        max_flow+=res[end];    }}int main(){    memset(first,-1,sizeof(first));    scanf("%d%d%d",&n,&f,&d);    int s=f+2*n+d+1;    for(int i=1;i<=f;i++)    {        add(0,i,1);        add(i,0,0);    }    for(int i=f+1;i<=f+n;i++)    {        add(i,i+n,1);        add(i+n,i,0);    }    for(int i=f+2*n+1;i<=f+2*n+d;i++)    {        add(i,s,1);        add(s,i,0);    }    for(int i=1;i<=n;i++)    {        int a,b;        scanf("%d%d",&a,&b);        for(int j=1;j<=a;j++)        {            int x;            scanf("%d",&x);            add(x,i+f,1);            add(i+f,x,0);         }        for(int j=1;j<=b;j++)        {            int x;            scanf("%d",&x);            add(i+n+f,x+f+2*n,1);            add(x+f+2*n,i+n+f,0);         }     }    int ans=EK(0,s);    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击