FZU2295 Human life:網絡流-最大權閉合子圖-二進制優化-第九屆福建省大學生程序設計競賽
阿新 • • 發佈:2018-08-27
man scrip blog memset return pac dinic type bool
?直接講建圖:源點S想每個任務連邊,流量為其收益,每個任務向其需要的技能連邊,每個任務向先修技能連邊,每個技能向匯點T連邊,流量為其花費。答案是\(sum_{任務}-maxflow\).
?難點在於有些任務不能同時完成。因為只有k(5)對,直接二進制枚舉所有對互斥情況。為1則不能選第一個任務,為0則不能選第二個任務。不選就是取反再異或一下。
?細節看代碼吧。
目錄
- Catalog
- Solution:
(有任何問題歡迎留言或私聊 && 歡迎交流討論哦
Catalog
Problem:Portal傳送門
?原題目描述在最下面。
?題意就是很裸的最大權閉合子圖。
?推薦閱讀:胡伯濤《最小割模型在信息學競賽中的應用》
?完完全全的模板題:新疆大學五月月賽-D-勤奮的楊老師
?本題題意:m(50)個任務,n個技能。完成每個任務由相應的收益,完成每個任務前必須學一些技能。有些技能由先修技能。
?有些任務不能同時完成。
Solution:
?訓練賽的時候聽隊友講完題意,一眼就直接建對圖了,但是沒敢敲,因為比賽剛開始,想先寫簽到題。
?詳細de題解啊啊啊
?難點在於有些任務不能同時完成。因為只有k(5)對,直接二進制枚舉所有對互斥情況。為1則不能選第一個任務,為0則不能選第二個任務。不選就是取反再異或一下。
?細節看代碼吧。
AC_Code:
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #define mme(a,b) memset((a),(b),sizeof((a))) using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int MXN = 2e2+7; const int MXE = MXN*MXN; struct DINIC{ int tot,vt,vs; int d[MXN],head[MXN]; struct lp{ int v,w,nex; }cw[MXE]; void add_edge(int a,int b,int c){ cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c; head[a]=tot; cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0; head[b]=tot; } bool bfs(){ memset(d,-1,sizeof(d)); queue<int>Q; Q.push(vt);d[vt]=0; while(!Q.empty()){ int u=Q.front(); Q.pop(); for(int i=head[u];i!=-1;i=cw[i].nex){ int v=cw[i].v; if(cw[i^1].w&&d[v]==-1){ d[v]=d[u]+1; Q.push(v); } } } return d[vs]!=-1; } int dfs(int x,int f){ if(x==vt||f==0) return f; int use=0,w; for(int i=head[x];i!=-1;i=cw[i].nex){ int to=cw[i].v; if(d[to]==d[x]-1 && cw[i].w){ w=dfs(to,min(cw[i].w,f-use)); cw[i].w-=w,cw[i^1].w+=w; use+=w; if(use==f) return f; } } return use; } void init(int st,int ed){ tot = -1; memset(head,-1,sizeof(head)); vs = st; vt = ed; } int max_flow(){ int ans=0; while(bfs())ans+=dfs(vs,INF); return ans; } }dinic; const int N = 105; int n, m, k; int vs, vt; struct lp{ int v,x; int a[N]; }ar[N],br[N]; int c[N],d[N]; int main(){ int tim; scanf("%d", &tim); while(tim--){ scanf("%d%d%d", &n, &m, &k); vs = 0;vt = m+n+1; for(int i = 1; i <= n; ++i){ int v,x; scanf("%d%d", &v, &x); ar[i].v=v;ar[i].x=x; for(int j = 0; j < x; ++j){ scanf("%d", &ar[i].a[j]); } } for(int i = 1; i <= m; ++i){ int v,x; scanf("%d%d", &v, &x); br[i].v=v;br[i].x=x; for(int j = 0; j < x; ++j){ scanf("%d", &br[i].a[j]); } } for(int i = 0; i < k; ++i){ scanf("%d%d", &c[i], &d[i]); --c[i];--d[i]; } int sta = 1 << k, ans = 0; //printf("%lld\n", 1<<50); for(int t = 0; t < sta; ++t){ LL hhh = (1LL<<m)-1; for(int i = 0; i < k; ++i){ LL x = 1LL<<c[i], y = 1LL<<d[i]; if(t&(1<<i)){ hhh &= (~x); }else{ hhh &= (~y); } } //printf("hhh = %d\n", hhh); dinic.init(vs, vt); for(int i = 1, v; i <= n; ++i){ dinic.add_edge(i+m,vt,ar[i].v); for(int j = 0; j < ar[i].x; ++j){ v = ar[i].a[j]; dinic.add_edge(i+m,v+m,INF); } } int sum = 0, tmp; for(int i = 1, v; i <= m; ++i){ if((hhh&(1LL<<(i-1)))==0)continue; dinic.add_edge(vs,i,br[i].v); sum += br[i].v; for(int j = 0; j < br[i].x; ++j){ v = br[i].a[j]; dinic.add_edge(i,v+m,INF); } } tmp = dinic.max_flow(); ans = max(ans, sum - tmp); } printf("%d\n", ans); } return 0; }
Problem Description:
FZU2295 Human life:網絡流-最大權閉合子圖-二進制優化-第九屆福建省大學生程序設計競賽