[网络流24题] 搭配飞行员
★★☆ 输入文件:flyer.in
输出文件:flyer.out
简单对比
时间限制:1 s 内存限制:128 MB
第一行,两个整数n与n1,表示共有n个飞行员(2<=n<=100),其中有n1名飞行员是正驾驶员.
下面有若干行,每行有2个数字a,b。表示正驾驶员a和副驾驶员b可以同机飞行。
第一行,1个整数,表示最大起飞的飞机数。
1 7
2 6
2 10
3 7
4 8
5 9
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 queue<int>q; 12 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 memset(fir,0,sizeof(fir)); 19 cnt=1;tot=tot_; 20 } 21 void add(int a,int b,int c){ 22 nxt[++cnt]=fir[a]; 23 cap[cnt]=c; 24 fir[a]=cnt; 25 to[cnt]=b; 26 } 27 void addedge(int a,int b,int c){ 28 add(a,b,c);add(b,a,0); 29 } 30 bool BFS(int S,int T){ 31 dis[T]=1;q.push(T); 32 while(!q.empty()){ 33 int x=q.front();q.pop(); 34 for(int i=fir[x];i;i=nxt[i]) 35 if(!dis[to[i]]){ 36 dis[to[i]]=dis[x]+1; 37 q.push(to[i]); 38 } 39 } 40 return dis[S]; 41 } 42 int Max_Flow(int S,int T){ 43 if(!BFS(S,T))return 0; 44 for(int i=0;i<tot;i++)fron[i]=fir[i]; 45 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 46 int ret=0,p=S,f,Min; 47 while(dis[S]<=tot){ 48 if(p==T){ 49 f=INF; 50 while(p!=S){ 51 f=min(f,cap[path[p]]); 52 p=to[path[p]^1]; 53 }ret+=f;p=T; 54 while(p!=S){ 55 cap[path[p]]-=f; 56 cap[path[p]^1]+=f; 57 p=to[path[p]^1]; 58 } 59 } 60 61 for(int &i=fron[p];i;i=nxt[i]) 62 if(cap[i]&&dis[to[i]]==dis[p]-1) 63 {path[p=to[i]]=i;break;} 64 65 if(!fron[p]){Min=tot; 66 if(--gap[dis[p]]==0)break; 67 for(int i=fir[p];i;i=nxt[i]) 68 if(cap[i])Min=min(Min,dis[to[i]]); 69 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 70 if(p!=S)p=to[path[p]^1]; 71 } 72 } 73 return ret; 74 } 75 }ISAP; 76 77 int main(){ 78 freopen("flyer.in","r",stdin); 79 freopen("flyer.out","w",stdout); 80 int n,m,S,T,a,b; 81 scanf("%d%d",&n,&m);S=0; 82 ISAP.Init(n+2);T=n+1; 83 for(int i=1;i<=n;i++){ 84 if(i<=m)ISAP.addedge(S,i,1); 85 else ISAP.addedge(i,T,1); 86 } 87 while(true){ 88 if(scanf("%d%d",&a,&b)==EOF) 89 break; 90 ISAP.addedge(a,b,1); 91 } 92 printf("%d\n",ISAP.Max_Flow(S,T)); 93 return 0; 94 }
[网络流24题] 太空飞行计划
★★☆ 输入文件:shuttle.in
输出文件:shuttle.out
简单对比
时间限制:1 s 内存限制:128 MB
【问题描述】
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={ I1, I2,…,In }。实验Ej 需要用到的仪器是I的子集Rj∈I。配置仪器Ik 的费用为ck 美元。实验Ej 的赞助商已同意为该实验结果支付pj 美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
【编程任务】
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
【数据输入】
第1行有2个正整数m和n(m,n <= 100)。m是实验数,n是仪器数。接下来的m行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。
【结果输出】
第1行是实验编号;第2行是仪器编号;最后一行是净收益。
【输入文件示例】shuttle.in
2 3 10 1 2 25 2 3 5 6 7
【输出文件示例】shuttle.out
1 2 1 2 3 17
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 bool a[maxn],b[maxn]; 12 queue<int>q; 13 int n,m,S,T,tot=0; 14 struct Net_Flow{ 15 int tot; 16 void Init(int tot_){ 17 memset(dis,0,sizeof(dis)); 18 memset(gap,0,sizeof(gap)); 19 memset(fir,0,sizeof(fir)); 20 cnt=1;tot=tot_; 21 } 22 void add(int a,int b,int c){ 23 nxt[++cnt]=fir[a]; 24 cap[cnt]=c; 25 fir[a]=cnt; 26 to[cnt]=b; 27 } 28 void addedge(int a,int b,int c){ 29 add(a,b,c);add(b,a,0); 30 } 31 bool BFS(int S,int T){ 32 dis[T]=1;q.push(T); 33 while(!q.empty()){ 34 int x=q.front();q.pop(); 35 for(int i=fir[x];i;i=nxt[i]) 36 if(!dis[to[i]]){ 37 dis[to[i]]=dis[x]+1; 38 q.push(to[i]); 39 } 40 } 41 return dis[S]; 42 } 43 int Max_Flow(int S,int T){ 44 if(!BFS(S,T))return 0; 45 for(int i=0;i<tot;i++)fron[i]=fir[i]; 46 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 47 int ret=0,p=S,f,Min; 48 while(dis[S]<=tot){ 49 if(p==T){ 50 f=INF; 51 while(p!=S){ 52 f=min(f,cap[path[p]]); 53 p=to[path[p]^1]; 54 }ret+=f;p=T; 55 while(p!=S){ 56 cap[path[p]]-=f; 57 cap[path[p]^1]+=f; 58 p=to[path[p]^1]; 59 } 60 } 61 62 for(int &i=fron[p];i;i=nxt[i]) 63 if(cap[i]&&dis[to[i]]==dis[p]-1) 64 {path[p=to[i]]=i;break;} 65 66 if(!fron[p]){Min=tot; 67 if(--gap[dis[p]]==0)break; 68 for(int i=fir[p];i;i=nxt[i]) 69 if(cap[i])Min=min(Min,dis[to[i]]); 70 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 71 if(p!=S)p=to[path[p]^1]; 72 } 73 } 74 return ret; 75 } 76 bool vis[maxn]; 77 void DFS(int p){ 78 vis[p]=1; 79 if(p<=n)a[p]=1;else b[p]=1; 80 for(int i=fir[p];i;i=nxt[i]) 81 if(cap[i]&&!vis[to[i]])DFS(to[i]); 82 } 83 int Solve(int S,int T){ 84 int ret=Max_Flow(S,T);DFS(S); 85 for(int i=n+1;i<=n+m;i++) 86 if(b[i])printf("%d ",i-n); 87 printf("\n"); 88 for(int i=1;i<=n;i++) 89 if(a[i])printf("%d ",i); 90 printf("\n"); 91 return ret; 92 } 93 }ISAP; 94 95 int main(){ 96 freopen("shuttle.in","r",stdin); 97 freopen("shuttle.out","w",stdout); 98 scanf("%d%d",&m,&n); 99 S=0;T=n+m+1;ISAP.Init(T+1); 100 for(int i=n+1;i<=n+m;i++){ 101 int v,a;char c; 102 scanf("%d",&v);tot+=v; 103 ISAP.addedge(S,i,v); 104 c=getchar(); 105 while(c!='\r'){ 106 scanf("%d",&a); 107 ISAP.addedge(i,a,INF); 108 c=getchar(); 109 } 110 } 111 for(int i=1,v;i<=n;i++){ 112 scanf("%d",&v); 113 ISAP.addedge(i,T,v); 114 } 115 printf("%d\n",tot-ISAP.Solve(S,T)); 116 return 0; 117 }
[网络流24题] 最小路径覆盖问题
★★ 输入文件:path3.in
输出文件:path3.out
评测插件
时间限制:1 s 内存限制:128 MB 算法实现题8-3 最小路径覆盖问题(习题8-13)
´问题描述:
给定有向图G=(V,E)。设P是G的一个简单路(顶点不相交)的集合。如果V中每个
顶点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶
点开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少
的路径覆盖。
设计一个有效算法求一个有向无环图G的最小路径覆盖。
提示:
设V={1,2,... ,n},构造网络G1=(V1,E1)如下:
每条边的容量均为1。求网络G1的(x0,y0)最大流。
´编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
´数据输入:
由文件input.txt提供输入数据。文件第1行有2个正整数n和m。n是给定有向无环图
G的顶点数,m是G的边数。接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。
´结果输出:
程序运行结束时,将最小路径覆盖输出到文件output.txt中。从第1行开始,每行输出
一条路径。文件的最后一行是最少路径数。
输入文件示例
input.txt
11 12
1 2 1 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 11 10 11
输出文件示例
output.txt
1 4 7 10 11 2 5 8 3 6 9 3
数据范围:
1<=n<=150,1<=m<=6000
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 int id[maxm],G[maxn]; 12 queue<int>q; 13 int n,m,S,T,tot=0; 14 struct Net_Flow{ 15 int tot; 16 void Init(int tot_){ 17 memset(dis,0,sizeof(dis)); 18 memset(gap,0,sizeof(gap)); 19 memset(fir,0,sizeof(fir)); 20 cnt=1;tot=tot_; 21 } 22 void add(int a,int b,int c,int p){ 23 nxt[++cnt]=fir[a]; 24 cap[cnt]=c; 25 fir[a]=cnt; 26 to[cnt]=b; 27 id[cnt]=p; 28 } 29 void addedge(int a,int b,int c,int p){ 30 add(a,b,c,p);add(b,a,0,p); 31 } 32 bool BFS(int S,int T){ 33 dis[T]=1;q.push(T); 34 while(!q.empty()){ 35 int x=q.front();q.pop(); 36 for(int i=fir[x];i;i=nxt[i]) 37 if(!dis[to[i]]){ 38 dis[to[i]]=dis[x]+1; 39 q.push(to[i]); 40 } 41 } 42 return dis[S]; 43 } 44 int Max_Flow(int S,int T){ 45 if(!BFS(S,T))return 0; 46 for(int i=0;i<tot;i++)fron[i]=fir[i]; 47 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 48 int ret=0,p=S,f,Min; 49 while(dis[S]<=tot){ 50 if(p==T){ 51 f=INF; 52 while(p!=S){ 53 f=min(f,cap[path[p]]); 54 p=to[path[p]^1]; 55 }ret+=f;p=T; 56 while(p!=S){ 57 cap[path[p]]-=f; 58 cap[path[p]^1]+=f; 59 p=to[path[p]^1]; 60 } 61 } 62 63 for(int &i=fron[p];i;i=nxt[i]) 64 if(cap[i]&&dis[to[i]]==dis[p]-1) 65 {path[p=to[i]]=i;break;} 66 67 if(!fron[p]){Min=tot; 68 if(--gap[dis[p]]==0)break; 69 for(int i=fir[p];i;i=nxt[i]) 70 if(cap[i])Min=min(Min,dis[to[i]]); 71 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 72 if(p!=S)p=to[path[p]^1]; 73 } 74 } 75 return ret; 76 } 77 int vis[maxn]; 78 int Solve(int S,int T){ 79 int ret=0; 80 Max_Flow(S,T); 81 for(int x=1;x<=n;x++) 82 for(int i=fir[x];i;i=nxt[i]) 83 if(to[i]>n&&cap[i]==0) 84 {G[x]=to[i]-n;break;} 85 86 for(int i=1;i<=n;i++) 87 if(!vis[i]){ 88 int p=i; 89 while(p){ 90 vis[p]=1; 91 printf("%d ",p); 92 p=G[p]; 93 }ret+=1; 94 printf("\n"); 95 } 96 return ret; 97 } 98 }ISAP; 99 100 int main(){ 101 freopen("path3.in","r",stdin); 102 freopen("path3.out","w",stdout); 103 scanf("%d%d",&n,&m); 104 S=0;T=2*n+1;ISAP.Init(T+1); 105 for(int i=1;i<=n;i++){ 106 ISAP.addedge(S,i,1,0); 107 ISAP.addedge(i+n,T,1,0); 108 } 109 for(int i=1,a,b;i<=m;i++){ 110 scanf("%d%d",&a,&b); 111 ISAP.addedge(a,b+n,1,i); 112 } 113 printf("%d\n",ISAP.Solve(S,T)); 114 return 0; 115 }
[网络流24题]魔术球问题
★★☆ 输入文件:balla.in
输出文件:balla.out
简单对比
时间限制:1 s 内存限制:128 MB
问题描述:
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可
放11个球。
´编程任务:
对于给定的n,计算在 n根柱子上最多能放多少个球。
´数据输入:
文件第1 行有 1个正整数n,表示柱子数。
´结果输出:
文件的第一行是球数。
数据规模
n<=60 保证答案小于1600
输入文件示例
4
输出文件示例
11
方案如下
1 8
2 7 9
3 6 10
4 5 11
每一行表示一个柱子上的球
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt=1,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 queue<int>q; 12 int n,m,S,T,tot=0; 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 tot=tot_; 19 } 20 void add(int a,int b,int c){ 21 nxt[++cnt]=fir[a]; 22 cap[cnt]=c; 23 fir[a]=cnt; 24 to[cnt]=b; 25 } 26 void addedge(int a,int b,int c){ 27 add(a,b,c);add(b,a,0); 28 } 29 bool BFS(int S,int T){ 30 dis[T]=1;q.push(T); 31 while(!q.empty()){ 32 int x=q.front();q.pop(); 33 for(int i=fir[x];i;i=nxt[i]) 34 if(!dis[to[i]]){ 35 dis[to[i]]=dis[x]+1; 36 q.push(to[i]); 37 } 38 } 39 return dis[S]; 40 } 41 int Max_Flow(int S,int T){ 42 if(!BFS(S,T))return 0; 43 for(int i=0;i<tot;i++)fron[i]=fir[i]; 44 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 45 int ret=0,p=S,f,Min; 46 while(dis[S]<=tot){ 47 if(p==T){ 48 f=INF; 49 while(p!=S){ 50 f=min(f,cap[path[p]]); 51 p=to[path[p]^1]; 52 }ret+=f;p=T; 53 while(p!=S){ 54 cap[path[p]]-=f; 55 cap[path[p]^1]+=f; 56 p=to[path[p]^1]; 57 } 58 } 59 60 for(int &i=fron[p];i;i=nxt[i]) 61 if(cap[i]&&dis[to[i]]==dis[p]-1) 62 {path[p=to[i]]=i;break;} 63 64 if(!fron[p]){Min=tot; 65 if(--gap[dis[p]]==0)break; 66 for(int i=fir[p];i;i=nxt[i]) 67 if(cap[i])Min=min(Min,dis[to[i]]); 68 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 69 if(p!=S)p=to[path[p]^1]; 70 } 71 } 72 return ret; 73 } 74 int sqr[maxn]; 75 int Solve(int S,int T){ 76 for(int i=1;i*i<4001;i++)sqr[i*i]=1; 77 for(int t=1;t<4001;t++){ 78 Init(t*2+1); 79 for(int i=2;i<cnt;i+=2){ 80 cap[i]=1; 81 cap[i+1]=0; 82 } 83 addedge(S,t*2,1); 84 addedge(t*2+1,T,1); 85 for(int i=1;i<t;i++) 86 if(sqr[i+t])addedge(i*2,t*2+1,1); 87 if(t-Max_Flow(S,T)>n)return t-1; 88 } 89 } 90 }ISAP; 91 92 93 int main(){ 94 freopen("balla.in","r",stdin); 95 freopen("balla.out","w",stdout); 96 int S,T; 97 scanf("%d",&n);S=0;T=1; 98 printf("%d\n",ISAP.Solve(S,T)); 99 return 0; 100 }
[网络流24题] 圆桌聚餐
★★ 输入文件:roundtable.in
输出文件:roundtable.out
评测插件
时间限制:1 s 内存限制:128 MB
4 5
4 5 3 5 3 5 2 6 4
1
1 2 4 5 1 2 3 4 5 2 4 5 1 2 3 4 5
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int n,m,cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 queue<int>q; 12 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 memset(fir,0,sizeof(fir)); 19 cnt=1;tot=tot_; 20 } 21 void add(int a,int b,int c){ 22 nxt[++cnt]=fir[a]; 23 cap[cnt]=c; 24 fir[a]=cnt; 25 to[cnt]=b; 26 } 27 void addedge(int a,int b,int c){ 28 add(a,b,c);add(b,a,0); 29 } 30 bool BFS(int S,int T){ 31 dis[T]=1;q.push(T); 32 while(!q.empty()){ 33 int x=q.front();q.pop(); 34 for(int i=fir[x];i;i=nxt[i]) 35 if(!dis[to[i]]){ 36 dis[to[i]]=dis[x]+1; 37 q.push(to[i]); 38 } 39 } 40 return dis[S]; 41 } 42 int Max_Flow(int S,int T){ 43 if(!BFS(S,T))return 0; 44 for(int i=0;i<tot;i++)fron[i]=fir[i]; 45 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 46 int ret=0,p=S,f,Min; 47 while(dis[S]<=tot){ 48 if(p==T){ 49 f=INF; 50 while(p!=S){ 51 f=min(f,cap[path[p]]); 52 p=to[path[p]^1]; 53 }ret+=f;p=T; 54 while(p!=S){ 55 cap[path[p]]-=f; 56 cap[path[p]^1]+=f; 57 p=to[path[p]^1]; 58 } 59 } 60 61 for(int &i=fron[p];i;i=nxt[i]) 62 if(cap[i]&&dis[to[i]]==dis[p]-1) 63 {path[p=to[i]]=i;break;} 64 65 if(!fron[p]){Min=tot; 66 if(--gap[dis[p]]==0)break; 67 for(int i=fir[p];i;i=nxt[i]) 68 if(cap[i])Min=min(Min,dis[to[i]]); 69 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 70 if(p!=S)p=to[path[p]^1]; 71 } 72 } 73 return ret; 74 } 75 void Solve(){ 76 for(int x=1;x<=m;x++){ 77 for(int i=fir[x];i;i=nxt[i]) 78 if(to[i]>m&&cap[i]==0) 79 printf("%d ",to[i]-m); 80 printf("\n"); 81 } 82 } 83 84 }ISAP; 85 86 int main(){ 87 freopen("roundtable.in","r",stdin); 88 freopen("roundtable.out","w",stdout); 89 int S,T,sum=0; 90 scanf("%d%d",&m,&n); 91 S=0;T=n+m+1;ISAP.Init(T+1); 92 for(int i=1,v;i<=m;i++){ 93 scanf("%d",&v);sum+=v; 94 ISAP.addedge(S,i,v); 95 } 96 97 for(int i=m+1,v;i<=m+n;i++){ 98 scanf("%d",&v); 99 ISAP.addedge(i,T,v); 100 } 101 102 for(int i=1;i<=m;i++) 103 for(int j=m+1;j<=n+m;j++) 104 ISAP.addedge(i,j,1); 105 106 if(ISAP.Max_Flow(S,T)==sum){ 107 printf("1\n"); 108 ISAP.Solve(); 109 } 110 else printf("0\n"); 111 return 0; 112 }
[网络流24题] 最长递增子序列
★★★☆ 输入文件:alis.in
输出文件:alis.out
简单对比
时间限制:1 s 内存限制:128 MB «问题描述:
给定正整数序列x1,..., xn。
(1)计算其最长递增子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长
度为s的递增子序列。
«编程任务:
设计有效算法完成(1)(2)(3)提出的计算任务。
«数据输入:
由文件alis.in提供输入数据。文件第1 行有1个正整数n(n<=500),表示给定序列的长度。接
下来的1 行有n个正整数x1,..., xn。
«结果输出:
程序运行结束时,将任务(1)(2)(3)的解答输出到文件alis.out中。第1 行是最长
递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出
的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。
输入文件示例 输出文件示例
alis.in
4
3 6 2 5
alis.out
2
2
3
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 queue<int>q; 12 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 memset(fir,0,sizeof(fir)); 19 cnt=1;tot=tot_; 20 } 21 void add(int a,int b,int c){ 22 nxt[++cnt]=fir[a]; 23 cap[cnt]=c; 24 fir[a]=cnt; 25 to[cnt]=b; 26 } 27 void addedge(int a,int b,int c){ 28 add(a,b,c);add(b,a,0); 29 } 30 bool BFS(int S,int T){ 31 dis[T]=1;q.push(T); 32 while(!q.empty()){ 33 int x=q.front();q.pop(); 34 for(int i=fir[x];i;i=nxt[i]) 35 if(!dis[to[i]]){ 36 dis[to[i]]=dis[x]+1; 37 q.push(to[i]); 38 } 39 } 40 return dis[S]; 41 } 42 int Max_Flow(int S,int T){ 43 if(!BFS(S,T))return 0; 44 for(int i=0;i<tot;i++)fron[i]=fir[i]; 45 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 46 int ret=0,p=S,f,Min; 47 while(dis[S]<=tot){ 48 if(p==T){ 49 f=INF; 50 while(p!=S){ 51 f=min(f,cap[path[p]]); 52 p=to[path[p]^1]; 53 }ret+=f;p=T; 54 while(p!=S){ 55 cap[path[p]]-=f; 56 cap[path[p]^1]+=f; 57 p=to[path[p]^1]; 58 } 59 } 60 61 for(int &i=fron[p];i;i=nxt[i]) 62 if(cap[i]&&dis[to[i]]==dis[p]-1) 63 {path[p=to[i]]=i;break;} 64 65 if(!fron[p]){Min=tot; 66 if(--gap[dis[p]]==0)break; 67 for(int i=fir[p];i;i=nxt[i]) 68 if(cap[i])Min=min(Min,dis[to[i]]); 69 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 70 if(p!=S)p=to[path[p]^1]; 71 } 72 } 73 return ret; 74 } 75 }ISAP; 76 77 int a[maxn]; 78 int f[maxn]; 79 int main(){ 80 freopen("alis.in","r",stdin); 81 freopen("alis.out","w",stdout); 82 int n,S,T,ans=1; 83 scanf("%d",&n);S=0; 84 ISAP.Init(n+2);T=n+1; 85 for(int i=1;i<=n;i++) 86 scanf("%d",&a[i]); 87 88 for(int i=1;i<=n;i++){ 89 f[i]=1; 90 for(int j=i-1;j>=1;j--) 91 if(a[i]>=a[j])f[i]=max(f[i],f[j]+1); 92 ans=max(f[i],ans); 93 } 94 printf("%d\n",ans); 95 96 for(int i=1;i<=n;i++){ 97 if(f[i]==1)ISAP.addedge(S,i,1); 98 if(f[i]==ans)ISAP.addedge(i,T,1); 99 for(int j=i-1;j;j--) 100 if(f[j]==f[i]-1&&a[i]>=a[j]) 101 ISAP.addedge(j,i,1); 102 } 103 printf("%d\n",ISAP.Max_Flow(S,T)); 104 ISAP.Init(n+2);S=0;T=n+1; 105 for(int i=1;i<=n;i++){ 106 if(f[i]==1)ISAP.addedge(S,i,1); 107 if(f[i]==ans)ISAP.addedge(i,T,1); 108 for(int j=i-1;j;j--) 109 if(f[j]==f[i]-1&&a[i]>=a[j]) 110 ISAP.addedge(j,i,1); 111 } 112 ISAP.addedge(S,1,n); 113 if(f[n]==ans)ISAP.addedge(n,T,n); 114 printf("%d\n",ISAP.Max_Flow(S,T)); 115 return 0; 116 }
[网络流24题] 试题库
★★ 输入文件:testlib.in
输出文件:testlib.out
评测插件
时间限制:1 s 内存限制:128 MB
输出文件示例
testlib.out
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int n,k,cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 queue<int>q; 12 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 memset(fir,0,sizeof(fir)); 19 cnt=1;tot=tot_; 20 } 21 void add(int a,int b,int c){ 22 nxt[++cnt]=fir[a]; 23 cap[cnt]=c; 24 fir[a]=cnt; 25 to[cnt]=b; 26 } 27 void addedge(int a,int b,int c){ 28 add(a,b,c);add(b,a,0); 29 } 30 bool BFS(int S,int T){ 31 dis[T]=1;q.push(T); 32 while(!q.empty()){ 33 int x=q.front();q.pop(); 34 for(int i=fir[x];i;i=nxt[i]) 35 if(!dis[to[i]]){ 36 dis[to[i]]=dis[x]+1; 37 q.push(to[i]); 38 } 39 } 40 return dis[S]; 41 } 42 int Max_Flow(int S,int T){ 43 if(!BFS(S,T))return 0; 44 for(int i=0;i<tot;i++)fron[i]=fir[i]; 45 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 46 int ret=0,p=S,f,Min; 47 while(dis[S]<=tot){ 48 if(p==T){ 49 f=INF; 50 while(p!=S){ 51 f=min(f,cap[path[p]]); 52 p=to[path[p]^1]; 53 }ret+=f;p=T; 54 while(p!=S){ 55 cap[path[p]]-=f; 56 cap[path[p]^1]+=f; 57 p=to[path[p]^1]; 58 } 59 } 60 61 for(int &i=fron[p];i;i=nxt[i]) 62 if(cap[i]&&dis[to[i]]==dis[p]-1) 63 {path[p=to[i]]=i;break;} 64 65 if(!fron[p]){Min=tot; 66 if(--gap[dis[p]]==0)break; 67 for(int i=fir[p];i;i=nxt[i]) 68 if(cap[i])Min=min(Min,dis[to[i]]); 69 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 70 if(p!=S)p=to[path[p]^1]; 71 } 72 } 73 return ret; 74 } 75 void Solve(){ 76 for(int x=1;x<=k;x++){ 77 printf("%d: ",x); 78 for(int i=fir[x];i;i=nxt[i]) 79 if(to[i]>k&&!cap[i]) 80 printf("%d ",to[i]-k); 81 printf("\n"); 82 } 83 } 84 }ISAP; 85 86 int main(){ 87 freopen("testlib.in","r",stdin); 88 freopen("testlib.out","w",stdout); 89 int S,T,ans,tot=0; 90 scanf("%d%d",&k,&n); 91 S=0;T=n+k+1;ISAP.Init(T+1); 92 for(int i=1,v;i<=k;i++){ 93 scanf("%d",&v);tot+=v; 94 ISAP.addedge(S,i,v); 95 } 96 for(int i=k+1,v,x;i<=k+n;i++){ 97 scanf("%d",&v); 98 ISAP.addedge(i,T,v); 99 while(v--){ 100 scanf("%d",&x); 101 ISAP.addedge(x,i,1); 102 } 103 } 104 ans=ISAP.Max_Flow(S,T); 105 if(ans==tot)ISAP.Solve(); 106 else puts("NoSolution!"); 107 return 0; 108 }
[网络流24题] 机器人路径规划
★★★★ 输入文件:robotpath.in
输出文件:robotpath.out
简单对比
时间限制:1 s 内存限制:128 MB«问题描述:
机器人Rob可在一个树状路径上自由移动。给定树状路径T上的起点s 和终点t,机器
人Rob要从s运动到t。树状路径T上有若干可移动的障碍物。由于路径狭窄,任何时刻在
路径的任何位置不能同时容纳2 个物体。每一步可以将障碍物或机器人移到相邻的空顶点
上。设计一个有效算法用最少移动次数使机器人从s运动到t。
«编程任务:
对于给定的树T,以及障碍物在树T中的分布情况。计算机器人从起点s 到终点t的最
少移动次数。
«数据输入:
由文件robotpath.in提供输入数据。文件的第1 行有3 个正整数n,s和t,分别表示树T的
顶点数,起点s的编号和终点t 的编号。
接下来的n 行分别对应于树T 中编号为0,1,…,n-1 的顶点。每行的第1 个整数h
表示顶点的初始状态,当h=1 时表示该顶点为空顶点,当h=0 时表示该顶点为满顶点,其
中已有1 个障碍物。第2 个数k表示有k个顶点与该顶点相连。接下来的k个数是与该顶点
相连的顶点编号。
«结果输出:
程序运行结束时,将计算出的机器人最少移动次数输出到文件robotpath.out 中。如果无法
将机器人从起点移动到终点,输出“No solution!”。
输入文件示例 输出文件示例
robotpath.in
5 0 3
1 1 2
1 1 2
1 3 0 1 3
0 2 2 4
1 1 3
robotpath.out
3
此题太难,有时间再补。
[网络流24题] 方格取数问题
★★☆ 输入文件:grid.in
输出文件:grid.out
简单对比
时间限制:1 s 内存限制:128 MB
3 2 3
2 3 1
grid.out
11
(1<=N,M<=30)
之前已经写过。
[网络流24题] 餐巾
★★★ 输入文件:napkin.in
输出文件:napkin.out
简单对比
时间限制:5 s 内存限制:128 MB
【问题描述】
一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N)。餐厅可以从三种途径获得餐巾。
(1)购买新的餐巾,每块需p分;
(2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p)。如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此。
(3)把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f)。
在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部。在每天开始时,餐厅必须决定是否购买新餐巾及多少,使洗好的和新购的餐巾之和满足当天的需求量Ri,并使N天总的费用最小。
【输入】
输入文件共 3 行,第 1 行为总天数;第 2 行为每天所需的餐巾块数;第 3 行为每块餐巾的新购费用 p ,快洗所需天数 m ,快洗所需费用 f ,慢洗所需天数 n ,慢洗所需费用 s 。
【输出】
一行,最小的费用
【样例】
napkin.in
3
3 2 4
10 1 6 2 3
napkin.out
64
【数据规模】
n<=200,Ri<=50
之前已经写过。
[网络流24题] 软件补丁
★★ 输入文件:bugs.in
输出文件:bugs.out
简单对比
时间限制:1 s 内存限制:128 MB
【问题描述】
【输入格式】
【输出格式】
【输入输出样例】
8
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 #include <map> 6 using namespace std; 7 const int maxn=110; 8 const int INF=1000000000; 9 map<int,bool>vis; 10 map<int,int>dis; 11 int n,m,val[maxn]; 12 char op[maxn][maxn]; 13 char tp[maxn][maxn]; 14 queue<int>q; 15 int main(){ 16 freopen("bugs.in","r",stdin); 17 freopen("bugs.out","w",stdout); 18 scanf("%d%d",&n,&m); 19 for(int i=1;i<=m;i++){ 20 scanf("%d",&val[i]); 21 scanf("%s",op[i]+1); 22 scanf("%s",tp[i]+1); 23 } 24 25 q.push(0);vis[0]=1; 26 while(!q.empty()){ 27 int x=q.front(); 28 q.pop();vis[x]=0; 29 for(int t=1;t<=m;t++){ 30 int f=1; 31 for(int i=1;i<=n;i++) 32 if(!(x>>i-1&1)&&op[t][i]=='-'||x>>i-1&1&&op[t][i]=='+'){f=0;break;} 33 34 if(f==0)continue; 35 int y=x; 36 for(int i=1;i<=n;i++){ 37 if(tp[t][i]=='+')y&=((1<<n)-1)^(1<<(i-1)); 38 if(tp[t][i]=='-')y|=1<<(i-1); 39 } 40 if(dis[y]==0&&y)dis[y]=INF; 41 if(dis[x]+val[t]<dis[y]){ 42 dis[y]=dis[x]+val[t]; 43 if(!vis[y]){ 44 q.push(y); 45 vis[y]=1; 46 } 47 } 48 } 49 } 50 if(dis[(1<<n)-1]!=0) 51 printf("%d\n",dis[(1<<n)-1]); 52 else printf("-1\n"); 53 return 0; 54 }
[CTSC1999][网络流24题] 星际转移
★★★☆ 输入文件:home.in
输出文件:home.out
简单对比
时间限制:1 s 内存限制:128 MB
«问题描述:
由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了。
于是在月球上建立了新的绿地,以便在需要时移民。令人意想不到的是,2177 年冬由于未
知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球。现有n个太空站
位于地球与月球之间,且有m 艘公共交通太空船在其间来回穿梭。每个太空站可容纳无限
多的人,而每艘太空船i 只可容纳H[i]个人。每艘太空船将周期性地停靠一系列的太空站,
例如:(1,3,4)表示该太空船将周期性地停靠太空站134134134…。每一艘太空船从一个太
空站驶往任一太空站耗时均为1。人们只能在太空船停靠太空站(或月球、地球)时上、下船。
初始时所有人全在地球上,太空船全在初始站。试设计一个算法,找出让所有人尽快地全部
转移到月球上的运输方案。
«编程任务:
对于给定的太空船的信息,找到让所有人尽快地全部转移到月球上的运输方案。
«数据输入:
由文件home.in提供输入数据。文件第1行有3 个正整数n(太空站个数),m(太空船
个数)和k(需要运送的地球上的人的个数)。其中 1<=m<=13, 1<=n<=20, 1<=k<=50。
接下来的m行给出太空船的信息。第i+1 行说明太空船pi。第1 个数表示pi 可容纳的
人数Hpi;第2 个数表示pi 一个周期停靠的太空站个数r,1<=r<=n+2;随后r 个数是停靠
的太空站的编号(Si1,Si2,…,Sir),地球用0 表示,月球用-1 表示。时刻0 时,所有太空船都
在初始站,然后开始运行。在时刻1,2,3…等正点时刻各艘太空船停靠相应的太空站。人
只有在0,1,2…等正点时刻才能上下太空船。
«结果输出:
程序运行结束时,将全部人员安全转移所需的时间输出到文件home.out中。如果问题
无解,则输出0。
输入文件示例 输出文件示例
home.in
2 2 1
1 3 0 1 2
1 3 1 2 -1
home.out
5
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 int room[110],rnd[110][110],N,M,K;; 12 queue<int>q; 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 memset(fir,0,sizeof(fir)); 19 cnt=1;tot=tot_; 20 } 21 void add(int a,int b,int c){ 22 nxt[++cnt]=fir[a]; 23 cap[cnt]=c; 24 fir[a]=cnt; 25 to[cnt]=b; 26 } 27 void addedge(int a,int b,int c){ 28 add(a,b,c);add(b,a,0); 29 } 30 bool BFS(int S,int T){ 31 dis[T]=1;q.push(T); 32 while(!q.empty()){ 33 int x=q.front();q.pop(); 34 for(int i=fir[x];i;i=nxt[i]) 35 if(!dis[to[i]]){ 36 dis[to[i]]=dis[x]+1; 37 q.push(to[i]); 38 } 39 } 40 return dis[S]; 41 } 42 int Max_Flow(int S,int T){ 43 if(!BFS(S,T))return 0; 44 for(int i=0;i<tot;i++)fron[i]=fir[i]; 45 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 46 int ret=0,p=S,f,Min; 47 while(dis[S]<=tot){ 48 if(p==T){ 49 f=INF; 50 while(p!=S){ 51 f=min(f,cap[path[p]]); 52 p=to[path[p]^1]; 53 }ret+=f;p=T; 54 while(p!=S){ 55 cap[path[p]]-=f; 56 cap[path[p]^1]+=f; 57 p=to[path[p]^1]; 58 } 59 } 60 61 for(int &i=fron[p];i;i=nxt[i]) 62 if(cap[i]&&dis[to[i]]==dis[p]-1) 63 {path[p=to[i]]=i;break;} 64 65 if(!fron[p]){Min=tot; 66 if(--gap[dis[p]]==0)break; 67 for(int i=fir[p];i;i=nxt[i]) 68 if(cap[i])Min=min(Min,dis[to[i]]); 69 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 70 if(p!=S)p=to[path[p]^1]; 71 } 72 } 73 return ret; 74 } 75 #define add1 ((t-1)*N) 76 #define add2 ((t)*N) 77 bool Check(int mid){ 78 Init((mid+1)*N+3); 79 int ss=N*(mid+1)+1; 80 int S=0,T=N*(mid+1)+2; 81 addedge(S,ss,K); 82 for(int i=1;i<=M;i++){ 83 for(int t=1,p;t<=mid;t++){ 84 p=(t-1)%rnd[i][0]+1; 85 int u=rnd[i][p]; 86 int v=rnd[i][p%rnd[i][0]+1]; 87 if(u==-1||v==0) 88 continue; 89 if(u==0&&v==-1) 90 addedge(ss,T,room[i]); 91 else if(u==0) 92 addedge(ss,add2+v,room[i]); 93 else if(v==-1) 94 addedge(add1+u,T,room[i]); 95 else 96 addedge(add1+u,add2+v,room[i]); 97 } 98 } 99 for(int t=3;t<=mid;t++) 100 for(int i=1;i<=N;i++) 101 addedge((t-2)*N+i,(t-1)*N+i,INF); 102 return Max_Flow(S,T)>=K; 103 } 104 int Solve(){ 105 int lo=1,hi=500; 106 while(lo<=hi){ 107 int mid=(lo+hi)>>1; 108 if(Check(mid))hi=mid-1; 109 else lo=mid+1; 110 } 111 if(lo==501)lo=0; 112 return lo; 113 } 114 }ISAP; 115 116 117 118 int main(){ 119 freopen("home.in","r",stdin); 120 freopen("home.out","w",stdout); 121 scanf("%d%d%d",&N,&M,&K); 122 for(int i=1;i<=M;i++){ 123 scanf("%d",&room[i]); 124 scanf("%d",&rnd[i][0]); 125 for(int j=1;j<=rnd[i][0];j++) 126 scanf("%d",&rnd[i][j]); 127 } 128 printf("%d\n",ISAP.Solve()); 129 return 0; 130 }
[网络流24题] 运输问题
★★ 输入文件:tran.in
输出文件:tran.out
简单对比
时间限制:1 s 内存限制:128 MB«问题描述:
«编程任务:
对于给定的m 个仓库和n 个零售商店间运送货物的费用,计算最优运输方案和最差运
输方案。
«数据输入:
«结果输出:
程序运行结束时,将计算出的最少运输费用和最多运输费用输出到文件tran.out中。
输入文件示例 输出文件示例
tran.in
2 3
220 280
170 120 210
77 39 105
150 186 122
tran.out
48500
69140
对于所有数据:1<=N,M<=100
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=510; 7 const int maxm=8010; 8 const int INF=100000000; 9 int cnt=1,fir[maxn],nxt[maxm]; 10 int to[maxm],cap[maxm],val[maxm]; 11 void addedge(int a,int b,int c,int v){ 12 nxt[++cnt]=fir[a];to[cnt]=b; 13 cap[cnt]=c;val[cnt]=v;fir[a]=cnt; 14 } 15 16 queue<int>q; 17 int path[maxn]; 18 int dis[maxn],vis[maxn]; 19 int Spfa(int S,int T){ 20 for(int i=S+1;i<=T;i++) 21 dis[i]=INF; 22 q.push(S);vis[S]=1; 23 while(!q.empty()){ 24 int x=q.front(); 25 q.pop();vis[x]=0; 26 for(int i=fir[x];i;i=nxt[i]) 27 if(cap[i]&&dis[to[i]]>dis[x]+val[i]){ 28 dis[to[i]]=dis[x]+val[i]; 29 if(!vis[to[i]])q.push(to[i]); 30 vis[to[i]]=1;path[to[i]]=i; 31 } 32 } 33 return dis[T]==INF?0:dis[T]; 34 } 35 36 int Aug(int S,int T){ 37 int f=INF,p=T; 38 while(p!=S){ 39 f=min(f,cap[path[p]]); 40 p=to[path[p]^1]; 41 } 42 p=T; 43 while(p!=S){ 44 cap[path[p]]-=f; 45 cap[path[p]^1]+=f; 46 p=to[path[p]^1]; 47 } 48 return f; 49 } 50 51 int MCMF(int S,int T){ 52 int ret=0,d; 53 while(d=Spfa(S,T)) 54 ret+=Aug(S,T)*d; 55 return ret; 56 } 57 58 int S,T; 59 int n,m; 60 int main(){ 61 freopen("tran.in","r",stdin); 62 freopen("tran.out","w",stdout); 63 scanf("%d%d",&m,&n);S=0;T=n+m+1; 64 for(int i=1,x;i<=m;i++){ 65 scanf("%d",&x); 66 addedge(S,i,x,0); 67 addedge(i,S,0,0); 68 } 69 70 for(int i=m+1,x;i<=m+n;i++){ 71 scanf("%d",&x); 72 addedge(i,T,x,0); 73 addedge(T,i,0,0); 74 } 75 76 for(int i=1;i<=m;i++) 77 for(int j=m+1,x;j<=n+m;j++){ 78 scanf("%d",&x); 79 addedge(i,j,INF,x); 80 addedge(j,i,0,-x); 81 } 82 printf("%d\n",MCMF(S,T)); 83 for(int i=2;i<=cnt;i+=2){ 84 val[i]*=-1; 85 val[i^1]*=-1; 86 cap[i]+=cap[i^1]; 87 cap[i^1]=0; 88 } 89 printf("%d\n",-MCMF(S,T)); 90 return 0; 91 }
[网络流24题] 分配问题
★★ 输入文件:job.in
输出文件:job.out
简单对比
时间限制:1 s 内存限制:128 MB
«问题描述:
有n件工作要分配给n个人做。第i 个人做第j 件工作产生的效益为ij c 。试设计一个将
n件工作分配给n个人做的分配方案,使产生的总效益最大。
«编程任务:
对于给定的n件工作和n个人,计算最优分配方案和最差分配方案。
«数据输入:
由文件job.in提供输入数据。文件的第1 行有1 个正整数n,表示有n件工作要分配
给n 个人做。接下来的n 行中,每行有n 个整数ij c ,1≤i≤n,1≤j≤n,表示第i 个人做
第j件工作产生的效益为ij c 。
«结果输出:
程序运行结束时,将计算出的最小总效益和最大总效益输出到文件job.out中。
输入文件示例 输出文件示例
job.in
5
2 2 2 1 2
2 3 1 2 4
2 0 1 1 1
2 3 4 3 3
3 2 1 2 1
job.out
5
14
数据范围
N<=100
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=510; 7 const int maxm=8010; 8 const int INF=100000000; 9 int cnt=1,fir[maxn],nxt[maxm]; 10 int to[maxm],cap[maxm],val[maxm]; 11 void addedge(int a,int b,int c,int v){ 12 nxt[++cnt]=fir[a];to[cnt]=b; 13 cap[cnt]=c;val[cnt]=v;fir[a]=cnt; 14 } 15 16 queue<int>q; 17 int path[maxn]; 18 int dis[maxn],vis[maxn]; 19 int Spfa(int S,int T){ 20 for(int i=S+1;i<=T;i++) 21 dis[i]=INF; 22 q.push(S);vis[S]=1; 23 while(!q.empty()){ 24 int x=q.front(); 25 q.pop();vis[x]=0; 26 for(int i=fir[x];i;i=nxt[i]) 27 if(cap[i]&&dis[to[i]]>dis[x]+val[i]){ 28 dis[to[i]]=dis[x]+val[i]; 29 if(!vis[to[i]])q.push(to[i]); 30 vis[to[i]]=1;path[to[i]]=i; 31 } 32 } 33 return dis[T]; 34 } 35 36 int Aug(int S,int T){ 37 int f=INF,p=T; 38 while(p!=S){ 39 f=min(f,cap[path[p]]); 40 p=to[path[p]^1]; 41 } 42 p=T; 43 while(p!=S){ 44 cap[path[p]]-=f; 45 cap[path[p]^1]+=f; 46 p=to[path[p]^1]; 47 } 48 return f; 49 } 50 51 int MCMF(int S,int T){ 52 int ret=0,d; 53 while((d=Spfa(S,T))!=INF) 54 ret+=Aug(S,T)*d; 55 return ret; 56 } 57 58 int S,T; 59 int n; 60 int main(){ 61 freopen("job.in","r",stdin); 62 freopen("job.out","w",stdout); 63 scanf("%d",&n);S=0;T=2*n+1; 64 for(int i=1;i<=n;i++){ 65 addedge(S,i,1,0); 66 addedge(i,S,0,0); 67 addedge(i+n,T,1,0); 68 addedge(T,i+n,0,0); 69 } 70 71 for(int i=1;i<=n;i++) 72 for(int j=n+1,x;j<=2*n;j++){ 73 scanf("%d",&x); 74 addedge(i,j,1,x); 75 addedge(j,i,0,-x); 76 } 77 printf("%d\n",MCMF(S,T)); 78 for(int i=2;i<=cnt;i+=2){ 79 val[i]*=-1; 80 val[i^1]*=-1; 81 cap[i]+=cap[i^1]; 82 cap[i^1]=0; 83 } 84 printf("%d\n",-MCMF(S,T)); 85 return 0; 86 }
[网络流24题] 负载平衡
★★ 输入文件:overload.in
输出文件:overload.out
简单对比
时间限制:1 s 内存限制:128 MB
17 9 14 16 4
overload.out
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 using namespace std; 7 const int maxn=110; 8 int a[maxn],b[maxn]; 9 int main(){ 10 freopen("overload.in","r",stdin); 11 freopen("overload.out","w",stdout); 12 int n,tot=0; 13 scanf("%d",&n); 14 for(int i=1;i<=n;i++){ 15 scanf("%d",&a[i]); 16 tot+=a[i]; 17 } 18 tot/=n; 19 for(int i=1;i<n;i++){ 20 b[i]=tot-a[i]; 21 if(i>1)b[i]+=b[i-1]; 22 } 23 sort(b+1,b+n+1); 24 int ans=0; 25 for(int i=1;i<=n;i++) 26 ans+=abs(b[(n+1)/2]-b[i]); 27 28 printf("%d\n",ans); 29 return 0; 30 }
[网络流24题] 最长k可重线段集
[网络流24题] 最长k可重区间集
★★★ 输入文件:interv.in
输出文件:interv.out
简单对比
时间限制:1 s 内存限制:128 MB«问题描述:
«编程任务:
对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度。
«数据输入:
由文件interv.in提供输入数据。文件的第1 行有2 个正整数n和k,分别表示开区间的
个数和开区间的可重迭数。接下来的n行,每行有2个整数,表示开区间的左右端点坐标。
«结果输出:
程序运行结束时,将计算出的最长k可重区间集的长度输出到文件interv.out中。
输入文件示例 输出文件示例
interv.in
4 2
1 7
6 8
7 10
9 13
interv.out
15
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 using namespace std; 7 const int INF=233333333; 8 const int maxn=2010,maxm=20010; 9 int cnt,fir[maxn],nxt[maxm],to[maxm],cap[maxm],val[maxm],dis[maxn],path[maxn]; 10 struct data{ 11 int l,r,v; 12 bool operator <(const data A)const{ 13 if(l!=A.l) 14 return l<A.l; 15 return r<A.r; 16 } 17 }ar[maxn]; 18 19 struct data2{ 20 int a,pos; 21 bool operator <(const data2 A)const{ 22 if(a!=A.a) 23 return a<A.a; 24 return pos<A.pos; 25 } 26 }br[maxn]; 27 28 void addedge(int a,int b,int c,int v) 29 { 30 nxt[++cnt]=fir[a];to[cnt]=b;cap[cnt]=c;val[cnt]=v;fir[a]=cnt; 31 } 32 int S,T; 33 int Spfa() 34 { 35 queue<int>q; 36 memset(dis,-1,sizeof(dis)); 37 q.push(S);dis[S]=0; 38 while(!q.empty()) 39 { 40 int node=q.front();q.pop(); 41 for(int i=fir[node];i;i=nxt[i]) 42 if(cap[i]&&dis[node]+val[i]>dis[to[i]]){ 43 dis[to[i]]=val[i]+dis[node]; 44 path[to[i]]=i; 45 q.push(to[i]); 46 } 47 } 48 return dis[T]==-1?0:dis[T]; 49 } 50 51 int Aug() 52 { 53 int p=T,f=INF; 54 while(p!=S) 55 { 56 f=min(f,cap[path[p]]); 57 p=to[path[p]^1]; 58 } 59 p=T; 60 while(p!=S) 61 { 62 cap[path[p]]-=f; 63 cap[path[p]^1]+=f; 64 p=to[path[p]^1]; 65 } 66 return f; 67 } 68 69 int MCMF() 70 { 71 int ret=0,d; 72 while(d=Spfa()) 73 ret+=Aug()*d; 74 return ret; 75 } 76 77 int cont; 78 void Init() 79 { 80 cnt=1;cont=0; 81 memset(fir,0,sizeof(fir)); 82 } 83 84 int main() 85 { 86 freopen("interv.in","r",stdin); 87 freopen("interv.out","w",stdout); 88 int n,k; 89 { 90 Init(); 91 scanf("%d%d",&n,&k); 92 for(int i=1;i<=n;i++){ 93 scanf("%d%d",&ar[i].l,&ar[i].r); 94 ar[i].v=ar[i].r-ar[i].l; 95 } 96 sort(ar+1,ar+n+1); 97 for(int i=1;i<=n;i++){ 98 br[i*2-1].a=ar[i].l;br[i*2].a=ar[i].r; 99 br[i*2-1].pos=br[i*2].pos=i; 100 } 101 sort(br+1,br+2*n+1); 102 for(int i=1;i<=n;i++) 103 ar[i].l=ar[i].r=0; 104 for(int i=1;i<=2*n;i++) 105 { 106 int p=br[i].pos; 107 if(!ar[p].l){ 108 ar[p].l=++cont; 109 } 110 else{ 111 ar[p].r=++cont; 112 } 113 } 114 115 S=0;T=cont+1; 116 for(int i=0;i<cont+1;i++) 117 addedge(i,i+1,k,0),addedge(i+1,i,0,0); 118 for(int i=1;i<=n;i++) 119 addedge(ar[i].l,ar[i].r,1,ar[i].v),addedge(ar[i].r,ar[i].l,0,-ar[i].v); 120 printf("%d\n",MCMF()); 121 } 122 return 0; 123 }