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); } }