题目链接:http://poj.org/problem?id=1087
题面:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 15000 | Accepted: 5075 |
Description
Input
Output
Sample Input
4 A B C D 5 laptop B phone C pager B clock B comb X 3 B X X A X D
Sample Output
1
Source
题目大意:
有n个插座,m个抽头需要,便利店提供k种适配器,问最多有多少个插头可以使用。
解题:
这道题虽然不难,但是把模型抽象出来真的是比较麻烦。首先,不太明确,n个插座中是否有重复,所以用map排了下重。然后,给每种插座从1开始编号,然后统计每种插头需要数量。再给适配器中没有在插座中出现过的插头编号,将适配器中的插头看作插座,然后按适配器的关系,在两者间加一条无限的边。(因为我是反着跑得,所以加反向边)。然后,在源点到每个插座间加权值为他们的数量的边。然后根据插头,在同类型的插座和插头间,加无限的边。插头到汇点间加插头数量的边。(终于构完图了。。)跑一遍,减一下就是答案了!
代码:
#include <iostream> #include <cstdio> #include <queue> #include <string.h> #include <map> #include <string> using namespace std; #define arraySize 350 #define inf 1000000000 int capacity[arraySize][arraySize],flow[arraySize][arraySize],max_flow[arraySize],pre[arraySize]; //capacity存储点之间最大流量,flow存储点之间当前已经流过的流量 //max_flow存储每次遍历过程中的值,pre记录查找过程中每个节点的前一节点,用于后续更新 struct node { string a,b; }store[110]; int Edmonds_Karp(int source,int target)//源点,汇点 { //初始化 queue <int> store; int ans=0,cur; //cur当前节点 memset(flow,0,sizeof(flow)); while(true)//一直寻找增广路 { memset(max_flow,0,sizeof(max_flow)); memset(pre,0,sizeof(pre)); store.push(source); max_flow[source]=inf; while(!store.empty()) { cur=store.front(); store.pop(); for(int next=source;next<=target;next++) { //max_flow[next]恰可以用于标记是否访问过,同时要保证两点之间还有剩余流量 //这个过程中,可能会出现多条可行路径,但因为汇点只有一个会被先到达的路径抢占,故每个过程只能找到一条 if(!max_flow[next]&&capacity[cur][next]>flow[cur][next]) { store.push(next); //如果这两个点之间的值,比之前的最小值还小,则更新 max_flow[next]=min(max_flow[cur],capacity[cur][next]-flow[cur][next]); //记录前一个节点,用于后续更新 pre[next]=cur; } } } //说明已经找不到增广路了 if(max_flow[target]==0)break; //更新操作 for(int u=target;u!=source;u=pre[u]) { flow[pre[u]][u]+=max_flow[target]; //反向边 flow[u][pre[u]]-=max_flow[target]; } ans+=max_flow[target]; } return ans; } int main() { int n,m,k,cnt1,cnt2,ans; string tmp,use,a,b; cin>>n; cnt1=0; map <string,int> re; map <string,int> receptacle; map <string,int> plug; map <string,int> plug_num; //构图 for(int i=1;i<=n;i++) { cin>>tmp; re[tmp]++; } map <string,int> ::iterator itt; for(itt=re.begin();itt!=re.end();itt++) { receptacle[itt->first]=++cnt1; } cin>>m; for(int i=1;i<=m;i++) { cin>>tmp>>use; plug[use]++; } cin>>k; cnt2=cnt1; for(int i=1;i<=k;i++) { cin>>a>>b; store[i].a=a; store[i].b=b; if(!receptacle.count(a)) receptacle[a]=++cnt2; if(!receptacle.count(b)) receptacle[b]=++cnt2; } memset(capacity,0,sizeof(capacity)); for(itt=receptacle.begin();itt!=receptacle.end();itt++) { capacity[0][receptacle[itt->first]]=re[itt->first]; } for(int i=cnt1+1;i<=cnt2;i++) capacity[0][i]=0; for(int i=1;i<=k;i++) capacity[receptacle[store[i].b]][receptacle[store[i].a]]=inf; map <string,int> ::iterator it; for(it=plug.begin();it!=plug.end();it++) { plug_num[it->first]=++cnt2; } //cout<<"cnt: "<<cnt<<endl; for(it=plug.begin();it!=plug.end();it++) { if(receptacle.count(it->first)) capacity[receptacle[it->first]][plug_num[it->first]]=inf; } for(it=plug.begin();it!=plug.end();it++) { capacity[plug_num[it->first]][cnt2+1]=plug[it->first]; } ans=Edmonds_Karp(0,cnt2+1); cout<<m-ans<<endl; return 0; }