//这个题做的蛋疼,,,自己的想法就是不对,归根结底还是对最大流这种基本的东西不熟悉,,它的内涵都不懂,自己真是水呀
//我第一想的办法是把regulator[]当做限制,WA,原因没分析到,这是WA代码
#include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int MAX=105,INF=1<<30; int regulator[MAX],m,cap[MAX][MAX],flow[MAX][MAX], startN,sink,t,a[MAX],n,p[MAX]; queue<int> q; int smallest(int i,int j,int k){ int s=i<j?i:j; return s<k?s:k; } int maxFlow(){ memset(flow,0,sizeof(flow)); int f=0,u; while(1){ memset(a,0,sizeof(a));//a代表指向结点[v]的增广路 a[0]=INF; q.push(0); //cout<<"s: "<<endl; while(!q.empty()){ u=q.front(); q.pop(); //cout<<u<<" "<<a[u]<<endl; for(int v=1;v<=n;v++){ if(!a[v]&&cap[u][v]>flow[u][v]&& regulator[v]>flow[u][v]){ p[v]=u; q.push(v); //if(v==1) // cout<<"ssssssssss: "<<u // <<" "<<flow[u][v]<<endl; a[v]=smallest(a[u],cap[u][v]-flow[u][v], regulator[v]); //regulator[v]-=a[v]; } } } if(!a[t]) break; //cout<<a[t]<<endl; for(u=t;u!=0;u=p[u]){ flow[p[u]][u]+=a[t];//从汇点开始更新正向流 flow[u][p[u]]-=a[t];//从汇点开始更新反向流 //regulator[u]-=a[t];//从汇点开始更新regulator } f+=a[t]; } return f; } int main() { freopen("i.txt","r",stdin); int v1,v2,w; regulator[0]=INF; while(cin>>n){ memset(cap,0,sizeof(cap)); for(int i=1;i<=n;i++) cin>>regulator[i]; cin>>m; for(int i=0;i<m;i++){ cin>>v1>>v2>>w; cap[v1][v2]=w; } cin>>startN>>sink; //cout<<startN<<" "<<sink<<endl; for(int i=0;i<startN;i++){ cin>>v1; //cout<<v1<<endl; cap[0][v1]=INF; } t=++n; regulator[t]=INF; for(int i=0;i<sink;i++){ cin>>v1; cap[v1][t]=regulator[v1]; } cout<<maxFlow()<<endl; } return 0; }
//然后我又想到了一个优化 就是两个点之间的容量cap只能是它u,v,的regulator 和他们边的cap的最小值,,结果居然水过去了,代码如下
#include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int MAX=105,INF=1<<30; int regulator[MAX],m,cap[MAX][MAX],flow[MAX][MAX], startN,sink,t,a[MAX],n,p[MAX]; queue<int> q; int smallest(int i,int j,int k){ int s=i<j?i:j; return s<k?s:k; } int maxFlow(){ memset(flow,0,sizeof(flow)); int f=0,u; while(1){ memset(a,0,sizeof(a));//a代表指向结点[v]的增广路 a[0]=INF; q.push(0); while(!q.empty()){ u=q.front(); q.pop(); for(int v=1;v<=n;v++){ if(!a[v]&&cap[u][v]>flow[u][v]){ p[v]=u; q.push(v); a[v]=a[u]<cap[u][v]-flow[u][v]? a[u]:cap[u][v]-flow[u][v]; //regulator[v]-=a[v]; } } } if(!a[t]) break; //cout<<a[t]<<endl; for(u=t;u!=0;u=p[u]){ flow[p[u]][u]+=a[t];//从汇点开始更新正向流 flow[u][p[u]]-=a[t];//从汇点开始更新反向流 //regulator[u]-=a[t];//从汇点开始更新regulator } f+=a[t]; } return f; } int main() { freopen("i.txt","r",stdin); int v1,v2,w; regulator[0]=INF; while(cin>>n){ memset(cap,0,sizeof(cap)); for(int i=1;i<=n;i++) cin>>regulator[i]; cin>>m; for(int i=0;i<m;i++){ cin>>v1>>v2>>w; cap[v1][v2]=smallest(w,regulator[v1],regulator[v2]); } cin>>startN>>sink; //cout<<startN<<" "<<sink<<endl; for(int i=0;i<startN;i++){ cin>>v1; //cout<<v1<<endl; cap[0][v1]=regulator[v1]; } t=++n; regulator[t]=INF; for(int i=0;i<sink;i++){ cin>>v1; cap[v1][t]=regulator[v1]; } cout<<maxFlow()<<endl; } return 0; }
//最后才是对的做法,,就是拆点,,其实我第一个思路就是这个,只是当时觉得麻烦没写,其实一点都不麻烦
#include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int MAX=105*2,INF=1<<30; int regulator[MAX],m,cap[MAX][MAX],flow[MAX][MAX], startN,sink,t,a[MAX],n,p[MAX], head[MAX],rear[MAX],dian; queue<int> q; int maxFlow(){ memset(flow,0,sizeof(flow)); int f=0,u; while(1){ memset(a,0,sizeof(a));//a代表指向结点[v]的增广路 a[0]=INF; q.push(0); while(!q.empty()){ u=q.front(); q.pop(); for(int v=1;v<=n;v++){ if(!a[v]&&cap[u][v]>flow[u][v]){ p[v]=u; q.push(v); a[v]=a[u]<cap[u][v]-flow[u][v]? a[u]:cap[u][v]-flow[u][v]; //regulator[v]-=a[v]; } } } if(!a[t]) break; //cout<<a[t]<<endl; for(u=t;u!=0;u=p[u]){ flow[p[u]][u]+=a[t];//从汇点开始更新正向流 flow[u][p[u]]-=a[t];//从汇点开始更新反向流 //regulator[u]-=a[t];//从汇点开始更新regulator } f+=a[t]; } return f; } int main() { freopen("i.txt","r",stdin); int v1,v2,w; regulator[0]=INF; while(cin>>n){ dian=1; memset(cap,0,sizeof(cap)); for(int i=1;i<=n;i++){ cin>>regulator[i]; head[i]=dian; rear[i]=dian+1; cap[dian][dian+1]=regulator[i]; dian+=2; } cin>>m; for(int i=0;i<m;i++){ cin>>v1>>v2>>w; cap[rear[v1]][head[v2]]=w; } cin>>startN>>sink; //cout<<startN<<" "<<sink<<endl; for(int i=0;i<startN;i++){ cin>>v1; //cap[0][v1]=regulator[v1]; cap[0][head[v1]]=INF; } //t=++n; t=n=dian; //regulator[t]=INF; for(int i=0;i<sink;i++){ cin>>v1; //cout<<v1<<endl; cap[rear[v1]][t]=INF; } /*for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cout<<cap[i][j]<<" "; } cout<<endl; }*/ cout<<maxFlow()<<endl; } return 0; }
//为什么我第2种方法是错的,第3种是对的呢?,可以看一下数据
3 100 50 25 3 1 2 100 2 3 100 1 3 100 1 2 1 2 3 3 100 20 30 2 2 1 100 3 1 100 3 1 1 2 3 1 8 20 15 17 5 10 25 20 50 10 1 4 15 1 5 5 2 5 10 2 6 10 3 6 25 6 5 10 4 7 10 5 7 15 5 8 10 6 8 15 3 2 1 2 3 7 8 5 20 15 10 20 20 4 1 3 5 2 3 10 3 4 10 3 5 10 2 2 1 2 4 5
//如果你仔细分析最后一个数据的结点5,你会发现第2种方法忽略了结点5的regulator是10的限制而让5结点流出了 15的流量