题意:在一个会议室里有n种插座,每种插座一个;每个插座只能插一种以及一个电器(或者适配器);
有m个电器,每个电器有一个插头需要插在相应一种插座上;不是所有电器都能在会议室找到相应插座;
有k种适配器,每种适配器可以有无限多数量;每种适配器(a, b)可以把b类插座变为a类插座;
问最后有多少个电器无法使用。
建图:
(1) 源点到每种插座连一条权值为1的边
(2) 每个电器到汇点连一条权值为1的边
(3) m个电器中,连一条对应插座到该个电器的边,权值为1
(4)k种适配器,连一条B到A的边,权值为inf
题目意思最多也就300个点,怎么开n=300,就re了,开600多,就AC了,求过路大神指点

1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 #include <map> 7 using namespace std; 8 #define inf 0x7fffffff 9 #define N 666 10 #define M 350000 11 map<string,int> mp; 12 struct Edge 13 { 14 int v,w,next; 15 Edge(){} 16 Edge(int V,int W,int NEXT):v(V),w(W),next(NEXT){} 17 }edge[M]; 18 int pre[N],cur[N],dis[N],gap[N]; 19 int size,head[N]; 20 int a[105]; 21 void Init() 22 { 23 memset(head,-1,sizeof(head)); 24 size = 0; 25 } 26 void InsertEdge(int u,int v,int w)// 加边 27 { 28 edge[size] = Edge(v,w,head[u]); 29 head[u] = size++; 30 edge[size] = Edge(u,0,head[v]); 31 head[v] = size++; 32 } 33 int Isap(int st,int ed,int n) // Isap模板 34 { 35 for(int i=0; i<=n; i++) 36 { 37 gap[i] = dis[i] = 0; 38 cur[i] = head[i]; 39 } 40 int u = pre[st] = st; 41 int aug = inf ,maxflow = 0; 42 while(dis[st] < n) 43 { 44 loop: 45 for(int &i=cur[u]; i!=-1; i=edge[i].next) 46 { 47 int v = edge[i].v; 48 if(edge[i].w && dis[u]==dis[v]+1) 49 { 50 aug = min(aug,edge[i].w); 51 pre[v] = u; 52 u = v; 53 if(v==ed) 54 { 55 maxflow += aug; 56 for(u=pre[u]; v!=st; v=u,u=pre[u]) 57 { 58 edge[cur[u]].w -= aug; 59 edge[cur[u]^1].w += aug; 60 } 61 aug = inf; 62 } 63 goto loop; 64 } 65 } 66 int mindis = n; 67 for(int i=head[u]; i!=-1; i=edge[i].next) 68 { 69 int v = edge[i].v; 70 if(edge[i].w && dis[v] < mindis) 71 { 72 cur[u] = i; 73 mindis = dis[v]; 74 } 75 } 76 if(--gap[dis[u]]==0) break; 77 gap[dis[u]=mindis+1]++; 78 u = pre[u]; 79 } 80 return maxflow; 81 } 82 83 int main() 84 { 85 int T,n,m,k,st,ed,nv; 86 string s1,s2; 87 Init(); 88 mp.clear(); 89 scanf("%d",&n); 90 st = 0 ; nv = 1; //源点st为0,nv初始化为1,方便源点从0开始 91 for(int i=0; i<n; i++) 92 { 93 cin>>s1; 94 if(mp.find(s1)==mp.end()) mp[s1] = nv++; //map映射 95 InsertEdge(st,mp[s1],1); //源点到每种插座连一条权值为1的边 96 } 97 scanf("%d",&m); 98 int cnt=0; 99 for(int i=0; i<m; i++) 100 { 101 cin>>s1>>s2; 102 if(mp.find(s1)==mp.end()) mp[s1] = nv++; //map映射 103 if(mp.find(s2)==mp.end()) mp[s2] = nv++; //map映射 104 InsertEdge(mp[s2],mp[s1],1); //m个电器中,连一条对应插座到该个电器的边,权值为1 105 a[cnt++] = mp[s1]; //数组a记录设备的结点号 106 } 107 scanf("%d",&k); 108 for(int i=0; i<k; i++) 109 { 110 cin>>s1>>s2; 111 if(mp.find(s1)==mp.end()) mp[s1] = nv++; //map映射 112 if(mp.find(s2)==mp.end()) mp[s2] = nv++; //map映射 113 InsertEdge(mp[s2],mp[s1],inf); //k种适配器,连一条B到A的边,权值为inf 114 } 115 ed = nv;// 汇点 116 for(int i=0; i<cnt; i++) 117 InsertEdge(a[i],ed,1); //每个电器到汇点连一条权值为1的边 118 nv++; 119 printf("%d ",m-Isap(st,ed,nv)); //输出的答案是设备数减去最大流 120 return 0; 121 }