P8215-[THUPC2022 初赛]分组作业【网络流】
正題
題目鏈接:https://www.luogu.com.cn/problem/P8215
題目大意
有2×n2\times n2×n個人,第2×i?12\times i-12×i?1和第2×i2\times i2×i個人一組,然后每個人可以選擇愿不愿意合作,愿意需要付出cic_ici?代價,不愿意是did_idi?代價,如果兩個人都愿意,可以選擇合作。如果一個人選擇愿意另一個人不愿意,那么愿意的那個人會產生eie_iei?的代價。
然后給出mmm對關系,然后題目描述開擺了
1≤n≤5000,0≤m≤10000,1≤ai,bi,ci,di,ei≤1091\leq n\leq 5000,0\leq m\leq 10000,1\leq a_i,b_i,c_i,d_i,e_i\leq 10^91≤n≤5000,0≤m≤10000,1≤ai?,bi?,ci?,di?,ei?≤109
解題思路
首先考慮c,d,ec,d,ec,d,e的貢獻,考慮用最小割。
首先c,dc,dc,d要選一個,所以它們肯定是串在一個點上的,所以S→i→TS\rightarrow i\rightarrow TS→i→T,SSS到iii的流量為ccc,iii到TTT的流量為ddd。
然后eee的貢獻就是一個選ccc一個選ddd時的貢獻,所以我們可以讓iii連向它的隊友,流量為eee,如果iii選了ccc,它隊友選了ddd,那么這條eee的邊也要割。
然后因為還有一個選擇是否合作,但是要求所有的都選擇ccc的貢獻,所以我們讓新建一個點WWW,S→WS\rightarrow WS→W的一條邊表示是否合作(如果連了就表示合作),然后WWW連向同一個隊的兩個點,
那么一個小組的圖大概就長這樣
然后考慮后面的貢獻就很麻煩了
這一個我們可以直接讓BBB所在組的WWW點連接AAA點就行了,如果AAA選了ddd且BBB的合作邊沒被割掉,那么剛好這條路就是通的,也需要被割掉。
至于
這個貢獻,我們考慮反過來處理。
我們發現S→WiS\rightarrow W_iS→Wi?這條邊還沒有權值,我們可以先默認如果AAA沒有合作就會產生aia_iai?的代價,然后如果BBB選擇了不愿意,那么就會少產生aia_iai?的貢獻,我們讓BBB的ddd值減去aia_iai?。
然后發現如果此時AAA沒有合但是BBB不愿意也會少產生這個貢獻,我們讓WAW_AWA?連向BBB費用為aia_iai?,這樣這種情況就不會少算了。
然后因為ddd可能減到負數,我們可以讓所有的ccc和ddd加上一個大整數,然后最后統一減去這部分貢獻就好了。
這樣就完美處理完了所有的條件
code
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define ll long long using namespace std; const ll N=5100*6; struct node{ll to,next,w; }a[N<<4]; ll n,m,s,t,c[N],d[N],e[N],w[N]; ll tot=1,ls[N],dep[N],ans; queue<ll> q; void addl(ll x,ll y,ll w){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;return; } bool bfs(){while(!q.empty())q.pop();memset(dep,0,sizeof(dep));dep[s]=1;q.push(s);while(!q.empty()){ll x=q.front();q.pop();for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(!a[i].w||dep[y])continue;dep[y]=dep[x]+1;if(y==t)return 1;q.push(y);}}return 0; } ll dinic(ll x,ll flow){ll rest=0,k;if(x==t)return flow;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(!a[i].w||dep[y]!=dep[x]+1)continue;rest+=(k=dinic(y,min(flow-rest,a[i].w)));a[i].w-=k;a[i^1].w+=k;if(rest==flow)return flow;}if(!rest)dep[x]=0;return rest; } signed main() {scanf("%lld%lld",&n,&m);s=3*n+1;t=s+1;for(ll i=1;i<=2*n;i++)scanf("%lld%lld%lld",&c[i],&d[i],&e[i]);for(ll i=1,x,y,a,b;i<=m;i++){scanf("%lld%lld%lld%lld",&x,&y,&a,&b);ll A=(x+1)/2,B=(y+1)/2;addl(2*n+B,x,b);w[A]+=a;d[y]-=a;addl(2*n+A,y,a);}for(ll i=1;i<=2*n;i++){addl(s,i,d[i]+1e14);addl(i,t,c[i]+1e14);ll p=(i&1)?(i+1):(i-1);addl(i,p,e[i]);}for(ll i=1;i<=n;i++){addl(s,2*n+i,w[i]);addl(2*n+i,2*i-1,1e18);addl(2*n+i,2*i,1e18);}while(bfs())ans+=dinic(s,1e18);printf("%lld\n",ans-200000000000000ll*n);return 0; }總結
以上是生活随笔為你收集整理的P8215-[THUPC2022 初赛]分组作业【网络流】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WiFi + 红外 + 蓝牙:小米小爱音
- 下一篇: P8207-[THUPC2022 初赛]