codeforces gym 100357 J (网络流)
题目大意
有n种物品,m种建筑,p个人。 n,m,p∈[1,20]
每种建筑需要若干个若干种物品来建造。每个人打算建造一种建筑,拥有一些物品。
主角需要通过交易来建造自己的建筑,交易的前提是对方用多余的物品来换取自己需要的物品。
询问主角是否能建造成功自己的建筑,并给出方案。
解题分析
超级恶心的读入,而且有一组数据的给出方式里没有逗号,和样例所示不同= =
根据py的性质很容易想到用网络流来做。将每种物品拆成x,y两份。
若主角多了a物品b件,连一条S到物品a,x部流量为b的边。
若主角少了a物品b件,连一条物品a,y部到T流量为b的边。
若某人少了a物品b件,连一条物品a,x部流量为b到该人流量为b的边。
若某人多了a物品b件,连一条该人到物品a,y部流量为b到该人流量为b的边。 模拟了一次交易的进行。
再由每个物品的y部向每个物品的x部连一条流量为无穷大的边。 表示交易可以不停的进行。
跑一遍网络流,如果是满流的话,说明可以成功。
输出方案则再残量网络上进行一次dfs,将每一次的交易的情况依次输出。
参考程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define rep(i,x,y) for (int i=x;i<=y;i++) 5 //#define DEBUG 6 const int N=500; 7 const int INF=2000000000; 8 9 int n,m,p,sum,lt[N],cur[N],S,TT,T,dis[N]; 10 11 struct node{ 12 int u,v,f,nt; 13 }eg[N*2]; 14 15 16 map <string,int> build_number; 17 map <string,int> res_number; 18 string res_name[N]; 19 string build_name[N]; 20 string people_name[N]; 21 string my_build; 22 23 int build_need[N][N]; 24 int people_has[N][N]; 25 26 void add(int u,int v,int f) 27 { 28 #ifdef DEBUG 29 cout<<u<<" "<<v<<" "<<f<<endl; 30 #endif 31 eg[++sum]=(node){u,v,f,lt[u]}; lt[u]=sum; 32 eg[++sum]=(node){v,u,0,lt[v]}; lt[v]=sum; 33 } 34 35 bool bfs() 36 { 37 memset(dis,0,sizeof(dis)); 38 queue <int> Q; 39 dis[S]=1; Q.push(S); 40 while (!Q.empty()) 41 { 42 int u=Q.front(); Q.pop(); 43 for (int i=lt[u];i;i=eg[i].nt) 44 { 45 int v=eg[i].v; 46 if (eg[i].f && !dis[v]) 47 { 48 dis[v]=dis[u]+1; 49 Q.push(v); 50 } 51 } 52 } 53 return dis[T]; 54 } 55 56 int dfs(int u,int flow) 57 { 58 if (u==T) return flow; 59 int res=0,f; 60 for (int &i=cur[u];i;i=eg[i].nt) 61 { 62 int v=eg[i].v; 63 if (eg[i].f && dis[v]==dis[u]+1) 64 { 65 f=dfs(v,min(flow-res,eg[i].f)); 66 res+=f; 67 eg[i].f-=f; eg[i^1].f+=f; 68 if (res==flow) break; 69 } 70 } 71 return res; 72 } 73 74 int dinic() 75 { 76 int sum=0; 77 while (bfs()) 78 { 79 rep(i,S,T) cur[i]=lt[i]; 80 sum+=dfs(S,INF); 81 } 82 return sum; 83 } 84 85 void solve(int u,int fa) 86 { 87 //cout<<u<<" "<<fa<<endl; 88 if (u==T) return; 89 for (int i=lt[u];i;i=eg[i].nt) 90 if (i%2==0 && eg[i^1].f) 91 { 92 int v=eg[i].v; 93 int times=1; 94 if (u==S) times=eg[i^1].f; 95 rep(j,1,times) 96 { 97 eg[i^1].f--; 98 if (u>=n+1 && u<=n+p) 99 { 100 //cout<<u-n<<" "<<fa<<" "<<v-n-p<<" "<<v<<endl; 101 cout<<"trade with "<<people_name[u-n]<<" "<<res_name[fa]<<" for "<<res_name[v-n-p]<<endl; 102 } 103 solve(v,u); 104 } 105 if (u!=S) break; 106 } 107 } 108 109 int main() 110 { 111 freopen("trading.in","r",stdin); 112 #ifndef DEBUG 113 freopen("trading.out","w",stdout); 114 #endif 115 char ch; 116 cin.sync_with_stdio(0); 117 memset(lt,0,sizeof(lt)); sum=1; 118 cin>>p>>n>>m; 119 S=0,TT=n*2+p+1,T=n*2+p+2; 120 int total=0; 121 rep(i,1,n) 122 { 123 cin>>res_name[i]; 124 res_number[res_name[i]]=i; 125 } 126 127 rep(i,1,m) 128 { 129 cin>>build_name[i]; 130 build_number[build_name[i]]=i; 131 string s; 132 cin>>s; 133 for (;;) 134 { 135 int x; 136 cin>>x>>s; 137 if (s[s.length()-1]==',') 138 { 139 s.erase(s.end()-1); 140 build_need[i][res_number[s]]=x; 141 } 142 else 143 { 144 build_need[i][res_number[s]]=x; 145 } 146 cin.get(ch); 147 if (ch=='\n') break; 148 } 149 } 150 151 string s; cin>>s>>s>>s; 152 153 154 if (s[s.length()-1]==',') s.erase(s.end()-1); 155 my_build=s; 156 cin.get(ch); 157 if (ch!='\n') 158 { 159 string t; cin>>t; 160 for (;;) 161 { 162 int x; cin>>x>>t; 163 if (t[t.length()-1]==',') 164 { 165 t.erase(t.end()-1); 166 people_has[1][res_number[t]]=x; 167 } 168 else 169 { 170 people_has[1][res_number[t]]=x; 171 } 172 cin.get(ch); 173 if (ch=='\n') break; 174 } 175 } 176 177 rep(i,1,n) 178 { 179 int y=people_has[1][i]-build_need[build_number[s]][i]; 180 if (y>0) add(S,i,y); 181 if (y<0) {add(i+n+p,TT,-y); total+=-y;} 182 } 183 184 add(TT,T,total); 185 186 rep(i,2,p) 187 { 188 string s; cin>>people_name[i]>>s>>s; 189 if (s[s.length()-1]==',') s.erase(s.end()-1); 190 cin.get(ch); 191 if (ch=='\n') continue; 192 string t; cin>>t; 193 for (;;) 194 { 195 int x; cin>>x>>t; 196 if (t[t.length()-1]==',') 197 { 198 t.erase(t.end()-1); 199 people_has[i][res_number[t]]=x; 200 } 201 else 202 { 203 people_has[i][res_number[t]]=x; 204 } 205 cin.get(ch); 206 //cout<<(int)ch<<endl; 207 if (cin.fail()) break; 208 if (ch=='\n') break; 209 } 210 rep(j,1,n) 211 { 212 //cout<<"\t"<<j<<" "<<people_has[i][j]<<" "<<build_need[build_number[s]][j]<<endl; 213 int y=people_has[i][j]-build_need[build_number[s]][j]; 214 if (y>0) add(i+n,n+p+j,y); 215 if (y<0) add(j,i+n,-y); 216 } 217 } 218 rep(i,1,n) add(n+p+i,i,INF); 219 220 int x=dinic(); 221 222 #ifdef DEBUG 223 cout<<x<<" "<<total<<endl; 224 #endif 225 if (x==total) {solve(S,0); cout<<"build "<<my_build<<endl;} 226 else cout<<"No way"<<endl; 227 }