POJ 1087 A Plug for UNIX 最大流

来源:互联网 发布:backtrack5软件下载 编辑:程序博客网 时间:2024/05/22 10:20

本题关键是建图,然后SAP水一个

建图:设0为源点,1为汇点,所以检索表里的插头下标要从2开始。

先输入n个插座,每个插座与汇点相连,值为1。

再输入m个用电器,用电器的名称其实是个无用的信息,把每个用电器的插头与源点相连,值为1。

然后输入k个转换器,如B X,则B与X连,注意值为INF(无穷大),因为这种类型的转换器可以有无数个。

最后SAP水一个,水题鉴定完毕。

View Code
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define INF 100000000#define maxn 405       //莫名其妙的RE,无奈开到405#define maxm 305int tot,head[maxn];struct node{    int v, next ,c;}edge[maxm * 2];    //双向别忘了*2;int dis[maxn],num[maxn];int cur[maxn],pre[maxn];int n, m, k, s, t, vs;void add(int x, int y, int c){    edge[tot].v=y;    edge[tot].c=c;    edge[tot].next=head[x];    head[x]=tot++;    edge[tot].v=x;    edge[tot].c=0;    edge[tot].next=head[y];    head[y]=tot++;}int cnt;char id[maxn][40],s1[40],s2[40];int sap()                  //sap非递归{    memset(dis,0,sizeof(dis));    memset(num,0,sizeof(num));    num[0]=vs=cnt;    int i, u=pre[s]=s,aug=INF,v,maxf=0;         for(i=0;i<=cnt;i++)cur[i]=head[i];    while(dis[s] < vs)    {loop:   for(i=head[u];i!=-1;i=edge[i].next)        {            v = edge[i].v;            if(edge[i].c>0&&dis[u]==dis[v]+1)            {                aug=min(aug,edge[i].c);                pre[v]=u;                cur[u]=i;                u=v;                if(u == t)                {                    for(u=pre[u];v!=s;v=u,u=pre[u])                    {                        edge[cur[u]].c -= aug;                        edge[cur[u]^1].c += aug;                    }                    maxf += aug;                    aug=INF;                }                goto loop;            }        }        int mind=vs;        for(i=head[u];i!=-1;i=edge[i].next)        {            v = edge[i].v;            if(dis[v]<mind&&edge[i].c>0)            {                mind=dis[v];                cur[u]=i;            }        }        if(!(--num[dis[u]]))break;        ++num[dis[u]=mind+1];        u=pre[u];    }    return maxf;}int find(char *s)    //建立检索表,找编号{    int i;    for(i=2;i<cnt;i++)        if(!strcmp(id[i],s))return i;    strcpy(id[i],s);    return cnt++;}int main(){    int i;    while(~scanf("%d",&n))    {        cnt=2;s=0;t=1;                 //0为源点,1为汇点。        memset(head,-1,sizeof(head));        tot=0;        for(i=1;i<=n;i++)        {            scanf("%s",s1);            add(find(s1),t,1);        }        scanf("%d",&m);        for(i=1;i<=m;i++)        {            scanf("%s%s",s1,s2);            add(s,find(s2),1);        }        scanf("%d",&k);        for(i=1;i<=k;i++)        {            scanf("%s%s",s1,s2);            add(find(s1),find(s2),INF);//注意INF        }        printf("%d\n",m-sap());    }}

 

原创粉丝点击