关键在建图,转换器连一条容量无限的边表示可以转化无数次,设备的插头连源点,插座连汇点。
dinic手敲已熟练,输出格式又被坑,总结一下,输出空行多case的,一个换行是必要的,最后一个不加空行,有Testcase最后一个不要换行,没有testcase最后一个要加换行,想起那天gold miner PE了两发。
对dinic网络流的简单理解:bfs找有没有增广路,dfs增广。
关键的概念:反向边,给一个反悔的机会。
#include<bits/stdc++.h> using namespace std; int n,m; map<string,int> mp; map<string,int>::iterator it; #define MP make_pair #define PB push_back #define fi first #define se second int id_cnt; int ID(const string &s) { if((it=mp.find(s))!=mp.end()) return it->se; mp.insert(MP(s,id_cnt)); return id_cnt++; } const int maxn = 404, INF = 0x3f3f3f3f; int S,T; struct Edge { int v,nxt,cap,flow; }edges[maxn<<1]; int head[maxn],cur[maxn],ecnt; void addEdge(int u,int v,int c) { edges[ecnt].nxt = head[u]; edges[ecnt].cap = c; edges[ecnt].flow = 0; edges[ecnt].v = v; head[u] = ecnt++; } void AddEdge(int u,int v,int c) { addEdge(u,v,c); addEdge(v,u,0); } int d[maxn]; bool vis[maxn]; bool bfs() { memset(vis,0,sizeof(bool)*id_cnt); queue<int> q; q.push(S); d[S] = 0; vis[S] = true; while(q.size()){ int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = edges[i].nxt){ Edge &e = edges[i]; if(!vis[e.v] && e.cap>e.flow){ vis[e.v] = true; d[e.v] = d[u]+1; q.push(e.v); } } } return vis[T]; } int dfs(int u,int a) { if(u == T||!a) return a; int flow = 0,f; for(int &i = cur[u]; ~i; i = edges[i].nxt){ Edge &e = edges[i]; if(d[e.v] == d[u]+1 && (f = dfs(e.v,min(a,e.cap-e.flow))>0)){ e.flow += f; edges[i^1].flow -= f; flow += f; a -= f; if(!a) break; } } return flow; } int MaxFlow() { int ret = 0; while(bfs()){ memcpy(cur,head,sizeof(int)*id_cnt); ret += dfs(S,INF); } return ret; } void init() { memset(head,-1,sizeof(head)); mp.clear(); id_cnt = 2; ecnt = 0; } int main() { //freopen("in.txt","r",stdin); char str1[42],str2[42]; int Testcase; scanf("%d",&Testcase); S = 0; T = 1; while(Testcase--){ int n,m,k; init(); scanf("%d",&n); for(int i = 0; i < n; i++){ scanf("%s",str1); AddEdge(ID(str1),T,1); } scanf("%d",&m); for(int i = 0; i < m; i++){ scanf("%s%s",str1,str2); AddEdge(S,ID(str2),1); } scanf("%d",&k); for(int i = 0; i < k; i++){ scanf("%s%s",str1,str2); AddEdge(ID(str1),ID(str2),INF); } int ans = m-MaxFlow(); printf("%d\n",ans); if(Testcase)putchar('\n'); } return 0; }