1. 程式人生 > >BZOJ - 1497 最小割應用

BZOJ - 1497 最小割應用

flow spa ont queue stack 邊表 ear class HA

題意:基站耗費成本,用戶獲得利益(前提是投入成本),求最大獲利
最小割的簡單應用,所有可能的收益-(消耗的成本/失去的收益),無窮大邊表示沖突,最小割求括號內的範圍即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set> #include<map> #include<ctime> #define rep(i,j,k) for(register int i=j;i<=k;i++) #define rrep(i,j,k) for(register int i=j;i>=k;i--) #define erep(i,u) for(register int i=head[u];~i;i=nxt[i]) #define iin(a) scanf("%d",&a) #define lin(a) scanf("%lld",&a) #define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a) #define s1(a) scanf("%s",a+1) #define print(a) printf("%lld",(ll)a) #define enter putchar(‘\n‘) #define blank putchar(‘ ‘) #define println(a) printf("%lld\n",(ll)a) #define IOS ios::sync_with_stdio(0) using namespace std; const int maxn = 2e5+11; const int oo = 0x3f3f3f3f; typedef
long long ll; ll read(){ ll x=0,f=1;register char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int to[maxn<<1],nxt[maxn<<1],cap[maxn<<1],flow[maxn<<1]; int head[maxn],tot; void init(){ memset(head,-1,sizeof head); tot=0; } void add(int u,int v,int w){ to[tot]=v; nxt[tot]=head[u]; cap[tot]=w; flow[tot]=0; head[u]=tot++; swap(u,v); to[tot]=v; nxt[tot]=head[u]; cap[tot]=0; flow[tot]=0; head[u]=tot++; } int n,m,s,t; int dis[maxn],pre[maxn],cur[maxn],gap[maxn]; bool vis[maxn]; struct QUEUE{ int que[maxn]; int front,rear; void init(){front=rear=0;} void push(int u){que[rear++]=u;} int pop(){return que[front++];} bool empty(){return front==rear;} }que; void bfs(){ memset(vis,0,sizeof vis); que.init(); que.push(t); vis[t]=1;dis[t]=0; while(que.empty()^1){ int u = que.pop(); for(int i = head[u]; ~i; i = nxt[i]){ register int v=to[i],c=cap[i^1],f=flow[i^1]; if(!vis[v]&&c>f){ vis[v]=1; dis[v]=dis[u]+1; que.push(v); } } } } int aug(){ int u=t,ans=oo; while(u!=s){ ans=min(ans,cap[pre[u]]-flow[pre[u]]); u=to[pre[u]^1]; } u=t; while(u!=s){ flow[pre[u]]+=ans; flow[pre[u]^1]-=ans; u=to[pre[u]^1]; } return ans; } int isap(){ int ans=0; bfs(); memset(gap,0,sizeof gap); memcpy(cur,head,sizeof head); for(int i = 1; i <= n; i++) gap[dis[i]]++; int u = s; while(dis[s]<n){ if(u==t){ ans+=aug(); u=s; } bool ok=0; for(int i = cur[u]; ~i; i = nxt[i]){ int v=to[i],c=cap[i],f=flow[i]; if(c>f&&dis[u]==dis[v]+1){ ok=1; pre[v]=i; cur[u]=i; u=v; break; } } if(!ok){ int mn=n-1; for(int i = head[u]; ~i; i = nxt[i]){ int v=to[i],c=cap[i],f=flow[i]; if(c>f) mn=min(mn,dis[v]); } if(--gap[dis[u]]==0) break; dis[u]=mn+1;gap[dis[u]]++;cur[u]=head[u]; if(u!=s) u=to[pre[u]^1]; } } return ans; } int main(){ while(cin>>n>>m){ init();s=1,t=1+n+m+1; #define guai(x) ((x)+n+1) rep(i,1,n){ int p=read(); add(s,1+i,p); } ll sum=0; rep(i,1,m){ int x=read(); int y=read(); int z=read();sum+=z; add(1+x,guai(i),oo); add(1+y,guai(i),oo); add(guai(i),t,z); } ll ans=isap(); println(sum-ans); } return 0; }

BZOJ - 1497 最小割應用