题目链接<http://poj.org/problem?id=1087>
题意:
有n个连接了电源的插座。m个设备,每个设备有对应的插头。有k个转换器,转换器能够让连接的插座进行转换,转换器无限个数。问最少有几个设备没法连接插座充电。
题解:
将每个插上电源的插座连接一个超级汇点,权值为1。
建一个超级源点连接每一个设备,权值为1。
设备与它对应的插头连接,权值为1。
转换器将两个插头连接,权值为无穷,因为转换器的个数是无穷。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
const int N=1e5+7;
const int inf=1e5+7;
struct Edge{
int u,v,w,next;
Edge(int u=0,int v=0,int w=0,int next=0):u(u),v(v),w(w),next(next){}
}edge[10*N];
int n,m,k,edn,sp,tp;
int p[N],d[N],c[N];
void add(int u,int v,int w){
edge[edn]=Edge(u,v,w,p[u]);p[u]=edn++;
edge[edn]=Edge(v,u,0,p[v]);p[v]=edn++;
}
bool bfs(){
memset(d,-1,sizeof(d));d[sp]=0;
queue<int>q;q.push(sp);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=p[u];~i;i=edge[i].next){
int v=edge[i].v;
if(d[v]==-1&&edge[i].w){
d[v]=d[u]+1;
q.push(v);
if(v==tp) return true;
}
}
}
return ~d[tp];
}
int dfs(int u,int b){
if(u==tp) return b;
int r=0;
for(int i=c[u];~i;i=edge[i].next){
int v=edge[i].v;
if(edge[i].w&&d[v]==d[u]+1){
int x=min(edge[i].w,b-r);
c[u]=i;
x=dfs(v,x);
r+=x;
edge[i].w-=x;
edge[i^1].w+=x;
if(r==b) break;
}
}
if(!r)d[u]=-2;
return r;
}
int dinic(){
int total=0,t;
while(bfs()){
memcpy(c,p,sizeof(p));
while(t=dfs(sp,inf))
total+=t;
}
return total;
}
string s;
map<string,int>a;
map<string,int>b;
int main()
{
memset(p,-1,sizeof(p));edn=0;
scanf("%d",&n);
int toa=1,tob=200;
sp=800,tp=sp+1;
for(int i=1;i<=n;i++){
cin>>s;
if(!b[s]) b[s]=++tob;
add(b[s],tp,1);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
cin>>s;
if(!a[s]) a[s]=++toa;
int u=a[s];
cin>>s;
if(!b[s]) b[s]=++tob;
int v=b[s];
add(u,v,1);
add(sp,u,1);
}
scanf("%d",&k);
for(int i=1;i<=k;i++){
cin>>s;
if(!b[s]) b[s]=++tob;
int u=b[s];
cin>>s;
if(!b[s]) b[s]=++tob;
int v=b[s];
add(u,v,inf);
}
printf("%d\n",m-dinic());
}