【网络流24题】【洛谷P2762】—太空飞行计划问题(最大权闭合子图)
死因:毒瘤读入
出这样读入的出题人应该拖出去阿了
这道题本身其实很简单的
和【BZOJ1497】【NOI2006】—最大获利几乎一模一样
直接建图跑就是了
由于最大权闭合图的点就是从起点开始广搜,权值为0的点不走,能走到的点就是被选中的点。dinic最后一次bfs的lev数组如果被走到了也就是要被选的。
但谁能告诉我为什么不能直接看边是否流满?
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
inline bool fuck(int &res)
{
res = 0; char ch = getchar();
while (!isdigit(ch)) { if (ch == '\n') return false; ch = getchar(); }
while (isdigit(ch)) { res = res * 10 + ch - '0'; ch = getchar(); }
if (ch == '\n') return false; else return true;
}
const int N=1505;
const int M=20005;
const int inf=20030224;
int n,m,k,cnt=1,adj[N],nxt[M<<1],to[M<<1],cap[M<<1],lev[N],val[N],tp[N],str,des,ans;
inline void addedge(int u,int v,int w){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,cap[cnt]=w;
nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,cap[cnt]=0;
}
inline bool bfs(){
memset(lev,-1,sizeof(lev));
queue<int> q;
q.push(str),lev[str]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(cap[e]>0&&lev[v]==-1){
lev[v]=lev[u]+1;
q.push(v);
if(v==des)return true;
}
}
}
return false;
}
int dinic(int u,int flow){
if(u==des)return flow;
int res=0;
for(int &e=tp[u];e;e=nxt[e]){
int v=to[e];
if(cap[e]>0&&lev[v]==lev[u]+1){
int mn=dinic(v,min(flow-res,cap[e]));
res+=mn,cap[e]-=mn,cap[e^1]+=mn;
if(res==flow)return res;
}
}
return res;
}
inline int solve(){
int res=0;
while(bfs()){
memcpy(tp,adj,sizeof(adj));
res+=dinic(str,inf);
}
return res;
}
int main(){
m=read(),n=read();str=n+m+1,des=str+1;
for(int i=1;i<=m;i++){
val[i]=read(),ans+=val[i];
addedge(str,i,val[i]);
int p;
while(fuck(p)){
addedge(i,m+p,inf);
}
addedge(i,m+p,inf);
}
for(int i=1;i<=n;i++){
val[m+i]=read();
addedge(m+i,des,val[m+i]);
}
ans-=solve();
for(int i=1;i<=m;i++)if(lev[i]>0)cout<<i<<" ";puts("");
for(int i=1;i<=n;i++)if(lev[i+m]>0)cout<<i<<" ";puts("");
cout<<ans<<'\n';
}