这道题很有意思,原题是只需输出最小割集大小,现在oj上改成了输出字典序最小的割集;
题解:可以考虑从小到大删边,若删掉这条边后,最小割变小,保持不变,记录此时的最小割大小;
若最小割不变,恢复这条边;
这样做的原因是什么呢?从小到大可以保证字典序的要求,删完边后若最小割减小,这条边一定在最小割上,删掉它不再恢复可以保证不在把这条通路上的其他边也收进来;
网络流博大精深,还是需要好好体会的;
但在此之前,应该先会敲代码;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<ctime> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=400; 10 const int inf=1000000000; 11 int S,T,n,m; 12 struct node{ 13 int y,next,re,flow; 14 }e[maxn<<4],e2[maxn<<4]; 15 int linkk[maxn],len=0; 16 void insert(int x,int y,int flow){ 17 e[++len].y=y; 18 e[len].next=linkk[x]; 19 linkk[x]=len; 20 e[len].flow=flow; 21 e[len].re=len+1; 22 e[++len].y=x; 23 e[len].next=linkk[y]; 24 linkk[y]=len; 25 e[len].flow=0; 26 e[len].re=len-1; 27 } 28 void init(){ 29 scanf("%d%d%d%d",&n,&m,&S,&T); 30 int x,y; 31 for(int i=1;i<=m;i++){ 32 scanf("%d%d",&x,&y); 33 if(x==S){insert(S,y,inf);insert(y+n,S,inf);} 34 else if(y==S){insert(S,x,inf);insert(x+n,S,inf);} 35 else if(x==T){insert(T,y,inf);insert(y+n,T,inf);} 36 else if(y==T){insert(x+n,T,inf);insert(T,x,inf);} 37 else {insert(x+n,y,inf);insert(y+n,x,inf);} 38 } 39 for(int i=1;i<=n;i++)if(S!=i&&T!=i)insert(i,i+n,1); 40 } 41 bool flag=1; 42 int flow=inf,vis[maxn],ans=0,f[maxn]; 43 void dfs(int x,int a){ 44 if(f[x])return; 45 vis[x]=1; 46 if(x==T){ 47 flag=1;flow=a;ans+=flow;return; 48 } 49 for(int i=linkk[x];i;i=e[i].next){ 50 if(vis[e[i].y]||(!e[i].flow))continue; 51 dfs(e[i].y,min(a,e[i].flow)); 52 if(flag){ 53 e[i].flow-=flow;e[e[i].re].flow+=flow;return; 54 } 55 } 56 } 57 void work(){ 58 ans=0;flag=1; 59 while(flag){ 60 flag=0; 61 memset(vis,0,sizeof(vis)); 62 dfs(S,inf); 63 } 64 } 65 int main(){ 66 freopen("1.in","r",stdin); 67 freopen("1.out","w",stdout); 68 init(); 69 memcpy(e2,e,sizeof(e)); 70 work(); 71 cout<<ans<<endl; 72 int q[maxn],sum=ans,k=ans,tail=0; 73 for(int i=1;i<=n;i++){ 74 if(i==S||i==T)continue; 75 memcpy(e,e2,sizeof(e)); 76 f[i]=1; 77 work(); 78 if(ans<sum)q[++tail]=i,sum=ans; 79 else f[i]=0; 80 } 81 sort(q+1,q+tail+1); 82 for(int i=1;i<=k;i++)printf("%d ",q[i]); 83 }
时间: 2024-10-11 23:08:13