裸的最小割题。求最小割和删掉的边(使得删掉的边最少)
第一问很简单,用“最大流=最小割”定理,直接求最大流即可。第二问我们可以将每条边从大到小排序,删掉这条边,再跑最大流,如果删后最大流和原来最大流的差等于这条边,那么我们就选这条边,用sum加上这条边,直到sum=原来最大流就可结束。
注意:删掉的边要按递增序排。
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 1<<29
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
using namespace std;
inline int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
int c[40][40],f[40][40],n,m,s,t,d[40];
inline bool bfs(){
memset(d,0,sizeof(d));
queue<int> q;
q.push(s);d[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int v=1;v<=n;++v){
if(c[u][v]>f[u][v]&&!d[v]){
q.push(v);
d[v]=d[u]+1;
if(v==t) return 1;
}
}
}
return 0;
}
inline int dinic(int u,int flow){
if(u==t) return flow;
int rest=flow;
for(int v=1;v<=n;++v){
if(c[u][v]>f[u][v]&&d[v]==d[u]+1){
int k=dinic(v,min(rest,c[u][v]-f[u][v]));
if(!k) d[v]=0;
f[u][v]+=k;
f[v][u]-=k;
rest-=k;
}
}
return flow-rest;
}
inline int maxf(){
int flow=0,maxflow=0;
while(bfs()){
while(flow=dinic(s,inf)) maxflow+=flow;
}
return maxflow;
}
struct node{
int u,v,w,i;
}ed[2005];
inline bool cmp(node x,node y){
return x.w>y.w;
}
int a[2005],ans;
int main()
{
freopen("milk6.in","r",stdin);
freopen("milk6.out","w",stdout);
n=read(),m=read();
s=1,t=n;
for(int i=1;i<=m;++i){
ed[i].u=read(),ed[i].v=read(),ed[i].w=read(),ed[i].i=i;
c[ed[i].u][ed[i].v]+=ed[i].w;
}
int maxflow=maxf(),sum=0;
printf("%d ",maxflow);
sort(ed+1,ed+m+1,cmp);
for(int i=1;i<=m;++i){
memset(f,0,sizeof(f));
c[ed[i].u][ed[i].v]-=ed[i].w;
int s=maxf();
if(s+ed[i].w==maxflow){
a[++ans]=ed[i].i;
sum+=ed[i].w;
if(sum==maxflow) break;
}
c[ed[i].u][ed[i].v]+=ed[i].w;
}
printf("%d\n",ans);
sort(a+1,a+ans+1);
for(int i=1;i<=ans;++i) printf("%d\n",a[i]);
return 0;
}