[bzoj1001]狼抓兔子 最小割
题意概述:给出一张无向图,每条边有一个权值,割掉这条边代价为它的权值,求使起点不能到达终点的最小代价。
显然能看出这是个最小割嘛,然后最小割=最大流,建图的时候特殊处理一下再跑个最大流就好了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int maxn=1e6,inf=1e9; inline int read() { register int X=0;register char ch=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar(); return X; } inline void write(int x) { if(x>9) write(x/10); putchar(x%10+'0'); } struct edge { int next,to,c,f; }e[maxn]; int head[maxn],cur[maxn],lev[maxn],s,t,n,m,tot; void add(int u,int v,int c) { e[tot].next=head[u],e[tot].c=c,e[tot].f=0,e[tot].to=v,head[u]=tot++; e[tot].next=head[v],e[tot].c=0,e[tot].f=0,e[tot].to=u,head[v]=tot++; } bool bfs() { memset(lev,0,sizeof(lev)); queue<int> q; q.push(s); lev[s]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to; if(!lev[v]&&e[i].c>e[i].f) { q.push(v); lev[v]=lev[u]+1; } } } return lev[t]!=0; } int dfs(int u,int cpf) { if(u==t) return cpf; int adf=0; for(int i=(cur[u]!=0?cur[u]:head[u]);i!=-1&&adf<cpf;i=e[i].next) { int v=e[i].to; if(lev[v]==lev[u]+1&&e[i].c>e[i].f) { int tmp=dfs(v,min(e[i].c-e[i].f,cpf-adf)); e[i].f+=tmp,e[i^1].f-=tmp; adf+=tmp; cur[u]=i; } } return adf; } int dinic() { int maxflow=0; while(bfs()) { memset(cur,0,sizeof(cur)); maxflow+=dfs(s,inf); } return maxflow; } int main() { n=read(),m=read(),s=read(),t=read(); memset(head,-1,sizeof(head)); for(int i=1;i<=m;i++) { int u=read(),v=read(),c=read(); add(u,v,c); } write(dinic()),putchar('\n'); }
ps:由于写这篇博客时代码并不在手上所以找了个最大流的模板,连边的时候改一下就好了,等找到代码或者重写一份再放一个完整版。
忘开longlong,忘用逆元,忘删调试信息,瞬间爆炸