#網路流,最大流,dinic#洛谷 3701 「偽模板」主席樹
阿新 • • 發佈:2018-12-11
題目
給出一些敵對關係,主席的生命需加上膜法師的數量,每打鬥一次減一條命,一共打m場,問一共能打贏多少場
分析
可以發現題目其實是求最大匹配,這樣理解就比較容易了,樣例解釋圖
程式碼
#include <cstdio> #include <vector> #include <queue> #define rr register #define r(i,a,b) for (rr int i=a;i<=b;i++) #define min(a,b) ((a)<(b))?(a):(b) using namespace std; struct node{ int y,w,next; }e[10001]; int a[101],b[101],c[101],d[101],ls[201],dis[201]; vector<int>p[6]; int n,m,s,t,k=1,ans; inline int in(){ rr int ans=0; rr char c=getchar(); while (c<48||c>57) c=getchar(); while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar(); return ans; } inline int read(){ rr char c=getchar(); rr int ans; while (c<65||c>90) c=getchar(); if (c=='J') ans=1; if (c=='H') ans=2; if (c=='W') ans=3; if (c=='Y') ans=4; if (c=='E') ans=5; while (c>64&&c<91) c=getchar(); return ans; } inline void add(int x,int y,int w){ e[++k]=(node){y,w,ls[x]}; ls[x]=k; e[++k]=(node){x,0,ls[y]}; ls[y]=k; } inline bool bfs(int s){ r(i,1,t) dis[i]=0; rr queue<int>q; q.push(s); dis[s]=1; while (q.size()){ rr int x=q.front(); q.pop(); for (rr int i=ls[x];i;i=e[i].next) if (e[i].w>0&&!dis[e[i].y]){ dis[e[i].y]=dis[x]+1; if (e[i].y==t) return 1; q.push(e[i].y); } } return 0; } inline int dfs(int x,int now){ if (x==t||!now) return now; rr int rest=0,f; for (rr int i=ls[x];i;i=e[i].next) if (e[i].w>0&&dis[e[i].y]==dis[x]+1){ rest+=(f=dfs(e[i].y,min(now-rest,e[i].w))); e[i].w-=f; e[i^1].w+=f; if (now==rest) return rest; } if (!rest) dis[x]=0; return rest; } int main(){ n=in(); rr int m=in(),cnt=0; s=n<<1|1; t=s+1; r(i,1,n) a[i]=read(); r(i,1,n) b[i]=read(); r(i,1,n) c[i]=in(); r(i,1,n) d[i]=in(); r(i,1,n) cnt+=a[i]==4; r(i,1,n) c[i]+=a[i]==1?cnt:0; cnt=0; r(i,1,n) cnt+=b[i]==4; r(i,1,n) d[i]+=b[i]==1?cnt:0;//主席加上膜法師的數量(補血) r(i,1,n) add(s,i,c[i]),add(i+n,t,d[i]); r(i,1,n) p[b[i]].push_back(i); r(i,1,n)//敵對關係建圖 if (a[i]==1){ if (p[2].size()) r(j,0,p[2].size()-1) add(i,p[2][j]+n,1); if (p[3].size()) r(j,0,p[3].size()-1) add(i,p[3][j]+n,1); } else if (a[i]==2){ if (p[3].size()) r(j,0,p[3].size()-1) add(i,p[3][j]+n,1); if (p[5].size()) r(j,0,p[5].size()-1) add(i,p[5][j]+n,1); } else if (a[i]==3){ if (p[4].size()) r(j,0,p[4].size()-1) add(i,p[4][j]+n,1); if (p[5].size()) r(j,0,p[5].size()-1) add(i,p[5][j]+n,1); } else if (a[i]==4){ if (p[1].size()) r(j,0,p[1].size()-1) add(i,p[1][j]+n,1); if (p[2].size()) r(j,0,p[2].size()-1) add(i,p[2][j]+n,1); } else if (a[i]==5){ if (p[1].size()) r(j,0,p[1].size()-1) add(i,p[1][j]+n,1); if (p[4].size()) r(j,0,p[4].size()-1) add(i,p[4][j]+n,1); } while (bfs(s)){//最大流 ans+=dfs(s,1e9); if (ans>m) return !printf("%d",m); } return !printf("%d",ans); }