poj-1807(最大流)

时间:2023-03-08 19:16:17
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);
}
}