poj-1807(最大流)

题意:给你n个插座,m个电器,每个电器有插头,还有k个插头转换器,可以把插座A变成插座B,转换器可以连续使用,比如A转换B,再从B转换C

解题思路:这道题就是题意麻烦,看懂了就很简单,首先建一个汇点和源点,源点与电器相连,权值为1,汇点与插座相连,边权为1,转换器中可以转换的插座相连,边权为inf

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<cstdio>
#include<map>
using namespace std;
const int maxn=100500;
const int inf=0x3f3f3f3f;
struct Edge
{
    int next,w,to,fa;
}edge[maxn];
int head[550],cnt,depth[550],Start,End;
map<string,int>M,M1;
int n,m,k,cot;
char s2[50];
char s1[50];
void add(int u,int v,int w)
{
   // cout<<"z"<<u<<" "<<v<<" "<<w<<endl;
    edge[cnt].next=head[u];edge[cnt].fa=u;
    edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt++;
    edge[cnt].next=head[v];edge[cnt].fa=v;
    edge[cnt].to=u;edge[cnt].w=0;head[v]=cnt++;
}
bool bfs()//分层;
{
    memset(depth,0,sizeof(depth));
    queue<int>q;
    q.push(Start);
    depth[Start]=1;
    while(!q.empty())
    {
        int temp=q.front();
        q.pop();
        for(int i=head[temp];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(depth[v]||edge[i].w<=0)
                continue;
            depth[v]=depth[temp]+1;
            q.push(v);
        }
    }
    return depth[End];//若为0表示没法到达也就是没有路径了;
}
int dfs(int u,int maxflow)
{
    if(u==End)
        return maxflow;
    int add=0;
    for(int i=head[u];i!=-1&&add<maxflow;i=edge[i].next)
    {
        int v=edge[i].to;
        if(depth[v]!=depth[u]+1)
            continue;
        if(edge[i].w==0)
            continue;
        int tempflow=dfs(v,min(edge[i].w,maxflow-add));
        edge[i].w-=tempflow;
        edge[i^1].w+=tempflow;
        add+=tempflow;
    }
    return add;
}
int dinic()
{
    int ans=0;
    while(bfs())
    {
        ans+=dfs(Start,0x3f3f3f3f);
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(head,-1,sizeof(head));
        M.clear();cnt=cot=0;Start=0;End=501;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s1);
            M[s1]=++cot;
            add(M[s1],End,1);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%s%s",s1,s2);
            if(!M[s1])
                M[s1]=++cot;
            if(!M[s2])
                M[s2]=++cot;
            add(Start,M[s1],1);
            add(M[s1],M[s2],1);
        }
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%s%s",s1,s2);
            if(!M[s1])
                M[s1]=++cot;
            if(!M[s2])
                M[s2]=++cot;
            add(M[s1],M[s2],inf);
        }
        int ans=dinic();
        printf("%d\n",m-ans);
    }
}

  

posted @ 2018-11-20 18:35  荒岛的龟  阅读(155)  评论(0编辑  收藏  举报