当前位置: 代码迷 >> 综合 >> poj 1815 Friendship 求字典序最小的最小割
  详细解决方案

poj 1815 Friendship 求字典序最小的最小割

热度:14   发布时间:2024-01-19 05:23:58.0

题意:

拆点后是求无向图字典序最小的最小割。

分析:

       设有边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);}}
}