题意:给你n个插座,然后接下俩的n行是对插座类型的描述,然后给你m个电器,接下来的m行是对电器的描述,电器的种类和电器的插座类型,然后给出k种转换器,接下来的
k行就是第一个字母表示该转换器可以和那种电器相连,第二个字母表示该转换器可以和那个插座相连,注意一种转换器可以有多个。。。。然后让你求得就是不能插上电源的电器有多少个。。
最大流的问题,0作为原点,每个电器的编号是1-m,转换器的编号是m+1到m+k,插座的编号是m+k+1到m+k+n,n+m+k+1作为汇点,求源点到汇点的最大流,然后m-最大流就是答案
建图部分,一定要建成有向图,而且在建图的过程中方向一定不能搞错。。
源点到每个电器的容量为1,然后能和电器相连的转换器的边容量为inf,直接和插座相连的电器的容量为1;转换器转换器之间的容量为inf,转换器和插座之间的容量inf,然后插座和汇点之间的容量是1
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<queue> const int inf=89999999; using namespace std; const int N=1000; struct node1 { string s1; }c[N]; struct node2 { string s1 ,s2; }d[N]; struct node3 { string s1,s2; }z[N]; struct node4 { int v,u; int next; int f; int cap; }G[N]; int a[1000]; int head[1000]; int p[1000]; int s,t,F; int num; void init() { memset(head,-1,sizeof(head)); num=0; } void add(int u,int v,int w) { G[num].u=u; G[num].v=v; G[num].cap=w; G[num].f=0; G[num].next=head[u]; head[u]=num++; int tt=u; u=v; v=tt; G[num].u=u; G[num].v=v; G[num].cap=0; G[num].f=0; G[num].next=head[u]; head[u]=num++; } void EK_() { queue<int>q; for(;;) { memset(p,-1,sizeof(p)); memset(a,0,sizeof(a)); a[s]=inf; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int k=head[u];k!=-1;k=G[k].next) { int v=G[k].v; if(!a[v]&&G[k].cap>G[k].f) { p[v]=k; q.push(v); a[v]=a[u]; if(a[v]>G[k].cap-G[k].f) a[v]=G[k].cap-G[k].f; } } } //cout<<a[t]<<endl; if(a[t]==0) break; for(int k=p[t];k!=-1;k=p[G[k].u]) { G[k].f+=a[t]; G[k^1].f-=a[t]; // printf("%d ",k^1); } F+=a[t]; } } void printf__() { printf("%d %d ",s,t); for(int i=0;i<num;i++) printf("%d %d %d ",G[i].u,G[i].v,G[i].cap); } int main() { int T; scanf("%d",&T); while(T--) { init(); int n,m,k; scanf("%d",&n); for(int i=1;i<=n;i++) cin>>c[i].s1; scanf("%d",&m); for(int i=1;i<=m;i++) cin>>d[i].s1>>d[i].s2; scanf("%d",&k); for(int i=1;i<=k;i++) cin>>z[i].s1>>z[i].s2; t=m+n+k+1; s=0; for(int i=1;i<=m;i++) { add(s,i,1); for(int j=1;j<=k;j++) { if(d[i].s2==z[j].s1) add(i,j+m,inf); } for(int j=1;j<=n;j++) { if(d[i].s2==c[j].s1) add(i,j+m+k,1); } } for(int i=1;i<=k;i++) { for(int j=1;j<=k;j++) { if(i!=j&&z[i].s2==z[j].s1) add(i+m,j+m,inf); } for(int j=1;j<=n;j++) { if(z[i].s2==c[j].s1) add(i+m,m+k+j,inf); } } for(int i=1;i<=n;i++) add(m+k+i,t,1); // printf__(); F=0; EK_(); int ans=m-F; printf("%d ",ans); if(T!=0) printf(" "); } return 0; }