题意:现在有m个设备,n种电源插座,k个适配器。适配器a b作用为可以把a插头转成b插头,也就是原来用a电源的设备现在可以用b电源
需要注意的几点:
1、"only one receptacle of each type",对于n种电源插座,每种类型只有一个
2、"No two devices will have exactly the same name",对于m个设备,彼此不相同
3、1<=m,n,k<=100,所以最多出现电源类型数为4*100=400,再加个m个设备与一个源点一个汇点,邻接矩阵的大小最少应为502.
4、适配器的数量是无限的
5、求最小几个设置没有电源
分析:一道很标准的网络最大流问题,关键在于建图
1、取源点、汇点分别标号0,1
2、源点到n个电源有容量为1的边
3、相应电源到m个设备有一条容量为1的边
4、m个设备到汇点有一条容量为1的边
5、k个适配器,如果a b,表示b电源可以转换成a电源,即电源b到电源a有一条容量无限的边
6、求源点到汇点网络最大流量
比较:这里也可以建图之前先用Floyd算法处理一下传递关系,即设备a如果用b电源,求出b电源可以转换的所有电源,这样也就说明设备a可以采用这些电源。这样可以减少建图的节点数,为m+n+2个节点。实验结果显示用Floyd算法处理后运行,运行时间增加,原因可能是Floyd是O(n3)时间复杂度。所以下面只给出基于分析没有采用Floyd处理的代码。
#include <iostream> #include <queue> #include <cstring> using namespace std; const int N = 512; const int INF = 1000000; const int NAME_LEN = 25; int cap[N][N]; /* creat graph, id(0) is src node, id(1) is snk node. * There are m rec nodes and n dev nodes. * One dev nodes can be connected to several rec nodes * due to kinds of adapaters using Floyd algrithmn * step 1:src node is connected to dev nodes with capacity 1. * step 2:dev nodes are connected to rec nodes with capacity 1. * step 3:rec nodes are connected to snk with capacity 1. * step 4:rec nodes are translated to another rec nodes with capacity INF */ void creatGraph(int &m,int &n,int &k, int &top){ int i,j; char rec[N][NAME_LEN]; char dev[NAME_LEN]; memset(cap,0,sizeof(cap)); memset(rec,0,sizeof(rec)); top=2; cin >> n; for(i=0;i<n;i++){ cin >> rec[top]; cap[0][top++]=1;/*step 1*/ } cin >> m; for(i=0;i<m;i++){ cin >> dev >> rec[top]; for(j=1;j<top;j++) if(strcmp(rec[top],rec[j])==0) break; if(j==top){ cap[top][top+1] = 1;/*step 1*/ cap[top+1][1] = 1;/*step 3*/ top +=2; }else{ cap[j][top] = 1;/*step 1*/ cap[top++][1] = 1;/*step 3*/ } } cin >> k; for(i=0;i<k;i++){ cin >> rec[top]; for(j=1;j<top;j++) if(strcmp(rec[j],rec[top])==0) break; int des=(j==top)?top++:j; cin >> rec[top]; for(j=0;j<top;j++) if(strcmp(rec[j],rec[top])==0) break; int src=(j==top)?top++:j; cap[src][des]=INF;/*step 4*/ } } int mf(int s, int t, int n) { int flow[N][N],lim[N],pre[N],f=0; queue<int> q; memset(flow,0,sizeof(flow)); while(true){ memset(lim,0,sizeof(lim)); lim[s]=INF;/*put src node in*/ q.push(s); while(!q.empty()){ int u=q.front();q.pop(); for(int v=0;v<n;v++) if(!lim[v] && cap[u][v]>flow[u][v]){ pre[v]=u; q.push(v); int dis = cap[u][v]-flow[u][v]; lim[v]=lim[u] < dis ? lim[u] : dis; } } if(lim[t]==0) break; for(int u=t;u!=s;u=pre[u]){ flow[pre[u]][u]+=lim[t]; flow[u][pre[u]]-=lim[t]; } f+=lim[t]; } return f; } int main() { int m, n, k,top,ans; creatGraph(m,n,k,top); ans=m-mf(0,1,top); cout << ans << endl; return 0; }