poj 1087 A Plug of UNIX Dinic邻接表算法解决

来源:互联网 发布:淘宝哪家家具店靠谱 编辑:程序博客网 时间:2024/06/05 09:45

    这个题目纠结的我要死。。。

   首先是最大流的第一次应用,  我一直认为是求最大流那错了。。。

  事实上,那里确实出错了一次。。。不过,那也无关紧要,主要是对那个字符串的处理,即将题目给的输入转化成一个图。

   这个过程,我仍然没有完全的清楚。所以导致了卡的太久。。。

   这个题,开始我自己想的时候,是想到了二分图,其实二分图,也差不多。

    最主要,最关键的还是建图。。。这个图你转化不过来的话,没搞手,,

   所以我觉得这个题,要分析的透彻了之后再动手打代码。。  不然你真的会付出代价的。。

    这个透彻是要全部理解了。。。

  首先,理解由多源点多汇点图,转化成单源单汇图。 N=(V,X,Y,A,C)  ==>  N=(V,s,t,A,C)。源点都在X集合里,汇点都在Y集合里。这样的一个S(X,Y)称为N的一个割。

   建立 s到X 集合里所有点的边 和 Y集合里的点到 t 的所有边。边上的权值等下说。

   s,t 称为人工源和人工汇,这个我们可以自己设置。

  到这里我们要将图建成功的话,就必须要知道X,Y这两个集合,以及X,Y两个集合之间的边。

  先来建立Y集合。

  Y集合的话也就是房间里的各个插座,将每个插座按输入的顺序标上序号。然后连上汇点 t。  边权都为1 。 因为近来一个就说明有一个被用了。最多也就那么多个。所以都是1


  X集合就是每个用电器的插座的名字,接着上面的序号按照输入顺序标号,这里要注意,假如某个用电器的插头是房间里有的,就直接用上面的已经标了的序号。 如果房间里没有对应的插座,那么就接着上面的序号按照输入的顺序标号,然后让s 与这些用电器的插头的序号 连接上,边权值就是这个插头出现的次数。


  最后就是X, Y 集合之间的边了。。 

  假如在名字和上面出现的有相同的,那么就用那个插头的序号。否则,继续接着上面的那个序号按输入顺序标号。然后将两个点连接起来,边权设为无穷大


到此为止,图建好了。

  然后直接求最大流就可以了。  几乎是一道最大流的模板题。

下面贴代码:

Source CodeProblem: 1087  User: 201141919106 Memory: 344K  Time: 0MS Language: C  Result: Accepted Source Code #include <stdio.h>#include <stdlib.h>#include<string.h>#define N 403#define Z N#define INF 0x7fffffffint V[N];int d[N];int next[N*3];int cap[N*3];int path[N];int E[N*3];int S,T,M;void init(int from,int to,int c){    M++;    cap[M]=c;    E[M]=to;    next[M]=V[from];    V[from]=M;}void insert(int from,int to,int c){    init(from,to,c);    init(to,from,0);}int bfs(){    int queue[N];    int f,t;    int x,i,y;    f=t=0;    memset(d,0,sizeof(d));    queue[t++]=S;    d[S]=1;    while(f!=t)    {        x=queue[f++];        for(i=V[x]; i; i=next[i])        {            y=E[i];            if(cap[i]>0&&d[y]==0)            {                d[y]=d[x]+1;                if(y==T)                {                    return 1;                }                queue[t++]=y;            }        }    }    return 0;}int dfs(){    int i,t,back,u,y;    int maxFlow=0;    int min;    t=1;    while(t)    {        u=(t==1)?S:E[path[t-1]];        if(u==T)        {            min=INF;            for(i=1; i<t; i++)            {                if(cap[path[i]]<min)                {                    min=cap[path[i]];                    back=i;                }            }            for(i=1; i<t; i++)            {                cap[path[i]]-=min;                cap[path[i]+1]+=min;            }            maxFlow+=min;            t=back;        }        else        {            for(i=V[u]; i; i=next[i])            {                y=E[i];                if(cap[i]>0&&(d[y]==d[u]+1))break;            }            if(i)            {                path[t++]=i;            }            else            {                d[u]=0;                t--;            }        }    }    return maxFlow;}int dinic(){    int maxFlow=0;    while(bfs())    {        maxFlow+=dfs();    }    return maxFlow;}int main(){    int n,m,j,q,r,i,c;    char s[Z][Z],str[Z],ch[Z];    int p[Z];    while(~scanf("%d\n",&n))    {        M=0;        S=0;        T=N-1;        memset(V,0,sizeof(V));        memset(p,0,sizeof(p));        memset(E,0,sizeof(E));        memset(cap,0,sizeof(cap));        memset(next,0,sizeof(next));        memset(s,0,sizeof(s));        memset(str,0,sizeof(str));        memset(ch,0,sizeof(ch));        for(i=1; i<=n; i++)        {            scanf("%s",s[i]);            insert(i,T,1);        }        c=n;        scanf("%d\n",&m);        for(i=0; i<m; i++)        {            scanf("%s %s",str,ch);            for(j=1; j<=c; j++)            {                if(strcmp(s[j],ch)==0)                {                    p[j]++;                    break;                }            }            if(j>c)            {                strcpy(s[++c],ch);                p[c]++;            }        }        scanf("%d\n",&r);        for(i=1; i<=r; i++)        {            scanf("%s%s",str,ch);            for(j=1; j<=c; j++)            {                if(strcmp(s[j],str)==0)                {                    break;                }            }            if(j>c)            {                strcpy(s[++c],str);            }            for(q=1; q<=c; q++)            {                if(strcmp(s[q],ch)==0)                {                    break;                }            }            if(q>c)            {                strcpy(s[++c],ch);            }            insert(j,q,INF);        }        for(i=1; i<=c; i++)        {            insert(S,i,p[i]);        }        printf("%d\n",m-dinic());    }    return 0;}





原创粉丝点击