LA 3487Duopoly(图论--网络流最小割 经典题)
Posted konjac蒟蒻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 3487Duopoly(图论--网络流最小割 经典题)相关的知识,希望对你有一定的参考价值。
题意:一个公司有一些资源,每种只有1割,有A、B两个公司分别对其中一些资源进行分组竞标。问卖资源的公司的最大收益。
解法:最小割。将A公司的竞标与源点相连,B公司的与汇点相连,边容量为竞标价。而A、B公司的竞标中有资源冲突的竞标之间连一条边,容量为INF。这样的最大收益就是 总竞标出价-割去竞标的边的价格的最小值。
问题!!dinic函数那里,我竟然2种打法相差了近乎3秒,也就是dfs函数流了很多次。。。(?Д?≡?Д?)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<queue> 6 using namespace std; 7 8 const int M=6100,N=300010,P=35,NN=6100,MM=240000,INF=1010; 9 int m,mm,len; 10 int id[N],last[NN],d[NN]; 11 struct edge{int y,fl,next;}a[MM]; 12 queue<int> q; 13 14 int mmin(int x,int y) {return x<y?x:y;} 15 void ins(int x,int y,int fl) 16 { 17 a[++len].y=y,a[len].fl=fl; 18 a[len].next=last[x],last[x]=len; 19 a[++len].y=x,a[len].fl=0; 20 a[len].next=last[y],last[y]=len; 21 } 22 bool bfs(int st,int ed) 23 { 24 while (!q.empty()) q.pop(); 25 memset(d,0,sizeof(d)); 26 q.push(st), d[st]=1; 27 while (!q.empty()) 28 { 29 int x=q.front(); q.pop(); 30 for (int i=last[x];i;i=a[i].next) 31 { 32 int y=a[i].y; 33 if (!a[i].fl||d[y]) continue; 34 d[y]=d[x]+1, q.push(y); 35 } 36 } 37 return d[ed]; 38 } 39 int dfs(int x,int flow,int ed) 40 { 41 if (x==ed) return flow; 42 int h=0; 43 for (int i=last[x];i;i=a[i].next) 44 { 45 int y=a[i].y; 46 if (!a[i].fl||d[y]!=d[x]+1) continue; 47 int t=dfs(y,mmin(flow-h,a[i].fl),ed); 48 h+=t; 49 a[i].fl-=t,a[i^1].fl+=t; 50 if (h==flow) break; 51 } 52 if (!h) d[x]=0; 53 return h; 54 } 55 int Max_flow(int st,int ed) 56 { 57 int h=0,p; 58 while(bfs(st,ed)) //h+=dfs(st,INF,ed);//slower a lot,very strange...... 59 while(p=dfs(st,INF,ed)) h+=p; 60 return h; 61 } 62 int main() 63 { 64 int T; 65 scanf("%d",&T); 66 for (int kase=1;kase<=T;kase++) 67 { 68 int d,x; char c; 69 int st=1,ed=2,sum=0; 70 len=1; 71 memset(last,0,sizeof(last)); 72 memset(id,0,sizeof(id)); 73 scanf("%d",&m); 74 for (int i=1;i<=m;i++) 75 { 76 scanf("%d",&d); c=getchar(); 77 sum+=d, ins(st,i+2,d); 78 while (c!=‘\n‘) 79 { 80 scanf("%d",&x); 81 id[x]=i+2, c=getchar(); 82 } 83 } 84 scanf("%d",&mm); 85 for (int i=1;i<=mm;i++) 86 { 87 scanf("%d",&d); c=getchar(); 88 sum+=d, ins(i+m+2,ed,d); 89 while (c!=‘\n‘) 90 { 91 scanf("%d",&x); 92 if (id[x]) ins(id[x],i+m+2,INF); 93 c=getchar(); 94 } 95 } 96 int ans=Max_flow(st,ed); 97 printf("Case %d:\n%d\n",kase,sum-ans); 98 if (kase<T) printf("\n"); 99 } 100 return 0; 101 }
以上是关于LA 3487Duopoly(图论--网络流最小割 经典题)的主要内容,如果未能解决你的问题,请参考以下文章