题意就是求s点到t点,最少去掉几个点使得他们不连通。如果无解输出NO ANSWER!
普通的最小割是求得边,而这里是要求点。我们拆点来做,拆点后的容量为1,而其他的是INF。
这样可以保证割的时候不会割到其他的边,而只会割容量为1的;
输出哪几个点,就是枚举删除每一个点。
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<iostream>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<cctype>
#include<set>
#include<ctime>
#include<cassert>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=1e9+7;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define in(x) (x)
#define out(x) (x+n)
int n,st,ed;
int start[210][210],pic[555][555],d[555];
bool del[555];
vector<int> pr;
void build(){
for(int i=1;i<=n;i++){
if(!del[i])
pic[in(i)][out(i)]=1;//拆点,后面枚举了割掉的点,所以用del数组标记
//容量是1,希望在割边的时候割它,割掉点中的边相当于割点,就把最小割转化成割点了
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)if(start[i][j]){
pic[out(i)][in(j)]=INF;
//割这条边的流量是INF,意味着不希望去割它
}
}
}
bool BFS(){
queue<int> Q;
memset(d,-1,sizeof d);
Q.push(st);d[st]=0;
while(!Q.empty()){
int s=Q.front();Q.pop();
for(int i=1;i<=n+n;i++){
if(pic[s][i]>0&&d[i]<0){
d[i]=d[s]+1;if(i==ed)return true;
Q.push(i);
}
}
}
return false;
}
int DFS(int s,int t,int flow){
if(s==t||flow==0)return flow;
int ans=0;
for(int i=1;i<=n+n;i++){
if(d[i]==d[s]+1&&pic[s][i]>0){
int ff=DFS(i,t,min(pic[s][i],flow));
if(ff>0){
pic[s][i]-=ff;
pic[i][s]+=ff;
ans+=ff;
flow-=ff;
if(!flow)break;
}
}
}
if(!ans)d[s]=-1;
return ans;
}
int dinic(){
int ans=0;
while(BFS()){
ans+=DFS(st,ed,INF);
}
return ans;
}
int main()
{
// freopen("D://input.txt","r",stdin);
scanf("%d%d%d",&n,&st,&ed);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&start[i][j]);
}
}
if(start[st][ed]){printf("NO ANSWER!\n");return 0;}
//只有直接相连的时候会无解
st=out(st);ed=in(ed);
build();
int ans=dinic();
printf("%d\n",ans);
if(!ans)return 0;
for(int i=1;i<=n;i++){
//因为割点可能会有很多组合,而且要求字典序最小,所以只能割一个就标记上,一直到割完为止
if(i==st-n||i==ed)continue;
del[i]=true;
build();
int t=dinic();
if(t<ans){
ans--;pr.PB(i);
if(ans==0)break;
}
else del[i]=false;;
}
for(int i=0;i<(int)pr.size();i++){
if(i)printf(" ");
printf("%d",pr[i]);
}
printf("\n");
return 0;
}