题意:
拆点后是求无向图字典序最小的最小割。
分析:
设有边e(u,v),则下面三点等价:
1:e可以作为割边(最小割集不唯一)。
2:去掉e后最小割值变小。
3:残量网络中不存在u到v的增广路。
所以从编号小的边开始,判断该边可不可能是割边,如果可能,把这条边去了,退流。如果不可能,保持原状,处理下一条边。
代码:
//poj 1815
//sep9
#include <iostream>
#include <queue>
using namespace std;
const int MAXN=512;
const int MAXM=20000;struct Edge
{int v,nxt,f;
}e[MAXM];
queue<int> que;
int src,sink;
int g[MAXN],dist[MAXN];
int nume;
bool vis[MAXN];int N,S,T,n,s,t,mark[MAXN];void addedge(int u,int v,int c)
{e[++nume].v=v;e[nume].f=c;e[nume].nxt=g[u];g[u]=nume; e[++nume].v=u;e[nume].f=0;e[nume].nxt=g[v];g[v]=nume;
}void init()
{ memset(g,0,sizeof(g)); nume=1;
} int bfs()
{ while(!que.empty()) que.pop(); memset(dist,0,sizeof(dist)); memset(vis,0,sizeof(vis)); vis[src]=true; que.push(src); while(!que.empty()){ int u=que.front();que.pop(); for(int i=g[u];i;i=e[i].nxt) if(e[i].f>0&&!vis[e[i].v]){ que.push(e[i].v); dist[e[i].v]=dist[u]+1; vis[e[i].v]=true; if(e[i].v==sink) return 1; } } return 0;
} int dfs(int u,int delta)
{ if(u==sink) return delta; int ret=0; for(int i=g[u];ret<delta&&i;i=e[i].nxt) if(e[i].f>0&&dist[e[i].v]==dist[u]+1){ int dd=dfs(e[i].v,min(e[i].f,delta-ret)); if(dd>0){ e[i].f-=dd; e[i^1].f+=dd; ret+=dd; } else dist[e[i].v]=-1; } return ret;
} int dinic()
{ int ret=0; while(bfs()==1) ret+=dfs(src,INT_MAX); return ret;
} int extend(int x,int a)
{if(x==2*a)return 1;vis[x]=1;for(int i=g[x];i;i=e[i].nxt)if(e[i].f&&!vis[e[i].v]&&extend(e[i].v,a))return 1; return 0;
}int extend(int a)
{memset(vis,0,sizeof(vis));return extend(2*a-1,a);
}int dfs1(int x,int t)
{if(x==t) return 1;vis[x]=1;for(int i=g[x];i;i=e[i].nxt)if(e[i].f&&!vis[e[i].v]&&dfs1(e[i].v,t)){--e[i].f;++e[i^1].f;return 1;}return 0;
}
void redo(int a)
{memset(vis,0,sizeof(vis));dfs1(sink,2*a);e[mark[a]].f=0,e[mark[a]^1].f=0;memset(vis,0,sizeof(vis));dfs1(2*a-1,src);
}int main()
{init();scanf("%d%d%d",&n,&s,&t);for(int i=1;i<=n;++i){mark[i]=nume+1;if(i!=s&&i!=t)addedge(2*i-1,2*i,1);elseaddedge(2*i-1,2*i,INT_MAX);}int x;for(int i=1;i<=n;++i)for(int j=1;j<=n;++j){scanf("%x",&x);if(x&&i!=j)addedge(2*i,2*j-1,INT_MAX);}src=2*s-1,sink=2*t;int ret=dinic();if(ret==INT_MAX) puts("NO ANSWER!");else{printf("%d\n",ret);for(int i=1;i<=n;++i)if(i!=s&&i!=t)if(!e[mark[i]].f&&!extend(i)){printf("%d ",i);redo(i);}}
}