【洛谷1361】 小M的作物(最小割)
阿新 • • 發佈:2019-03-18
ini main 每一個 題目 lse 貢獻 sum 代碼 mem
傳送門
洛谷
Solution
這是一個比較實用的套路,很多題目都有用,而且這個套路難以口胡出來。
考慮把每一個附加貢獻重新建一個點,然後向必需的點連邊,流量為val。
然後直接種植的從源點向這個點連,流量為val。
最後跑一個最小割就可以了。
代碼實現
#include<bits/stdc++.h> using namespace std; const int N=500010,Inf=1e9+10; int front[N],cnt,s,t,n; struct node { int to,nxt,w; }e[1500010]; queue<int>Q; int dep[N]; void Add(int u,int v,int w) { e[cnt]=(node){v,front[u],w};front[u]=cnt++; e[cnt]=(node){u,front[v],0};front[v]=cnt++; } bool bfs() { memset(dep,0,sizeof(dep)); Q.push(s);dep[s]=1; while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=front[u];i!=-1;i=e[i].nxt) { int v=e[i].to; if(!dep[v] && e[i].w) { dep[v]=dep[u]+1;Q.push(v); } } } return dep[t]; } int dfs(int u,int flow) { if(u==t || !flow)return flow; for(int i=front[u];i!=-1;i=e[i].nxt) { int v=e[i].to; if(dep[v]==dep[u]+1 && e[i].w) { int di=dfs(v,min(flow,e[i].w)); if(di) { e[i].w-=di;e[i^1].w+=di; return di; } else dep[v]=0; } } return 0; } int dinic() { int flow=0; while(bfs()) { while(int d=dfs(s,Inf))flow+=d; } return flow; } int m; int main() { memset(front,-1,sizeof(front)); scanf("%d",&n);int sum=0;t=100000; int tot=n; for(int i=1;i<=n;i++) { int x;scanf("%d",&x);sum+=x; Add(s,i,x); } for(int i=1;i<=n;i++) { int x;scanf("%d",&x);sum+=x; Add(i,t,x); } scanf("%d",&m); while(m--) { int k,c1,c2;scanf("%d%d%d",&k,&c1,&c2); ++tot;Add(s,tot,c1);Add(tot+1,t,c2); sum+=c1+c2; for(int i=1;i<=k;i++) { int id;scanf("%d",&id); Add(tot,id,Inf);Add(id,tot+1,Inf); } ++tot; } printf("%d\n",sum-dinic()); return 0; }
【洛谷1361】 小M的作物(最小割)