POJ 1815 最小割
2013-01-06 22:14
393 查看
题意:
n个人的两两关系矩阵,如果a认识b,则b认识a,且认识有传递性。给出一个s和一个t,问想让s不认识t,最少需要去掉多少人。
如果有解,输出字典序最小的解。
题解:
请特别注意0与NO ANSWER!的区别!
具体做法是:拆点限流,先求一次最小割为ans,然后从小到大枚举删除的点,重新建图再做最小割,如果当前结果比ans小,则更新ans,并把这个节点打上vis标记。
ps:已经打上vis标记的点不再参与之后重建图时
View Code
n个人的两两关系矩阵,如果a认识b,则b认识a,且认识有传递性。给出一个s和一个t,问想让s不认识t,最少需要去掉多少人。
如果有解,输出字典序最小的解。
题解:
请特别注意0与NO ANSWER!的区别!
具体做法是:拆点限流,先求一次最小割为ans,然后从小到大枚举删除的点,重新建图再做最小割,如果当前结果比ans小,则更新ans,并把这个节点打上vis标记。
ps:已经打上vis标记的点不再参与之后重建图时
View Code
#include <cstring> #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> #define N 500 #define M 40000 #define INF 1e9 using namespace std; int head ,to[M],next[M],len[M]; int q[M*4],layer ; bool map ,vis ; int n,S,T,tt,ss,cnt; inline void add(int u,int v,int w) { to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++; //printf("%d %d %d\n",u,v,w); } inline bool read() { memset(head,-1,sizeof head); cnt=0; memset(vis,0,sizeof vis); memset(map,0,sizeof map); S=0; T=n+n+1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&map[i][j]); if(map[ss][tt]) return false; add(S,ss,INF); add(tt+n,T,INF); for(int i=1;i<=n;i++) { if(i==ss||i==tt) add(i,i+n,INF); else add(i,i+n,1); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(map[i][j]&&i!=j) add(i+n,j,INF); return true; } inline void rebuild(int u) { memset(head,-1,sizeof head); cnt=0; add(S,ss,INF); add(tt+n,T,INF); for(int i=1;i<=n;i++) { if(i==ss||i==tt) add(i,i+n,INF); else if(i!=u&&!vis[i]) add(i,i+n,1); } for(int i=1;i<=n;i++) { if(i==u||vis[i]) continue; for(int j=1;j<=n;j++) if(map[i][j]&&j!=u&&i!=j&&!vis[j]) add(i+n,j,INF); } } inline bool bfs() { memset(layer,-1,sizeof layer); int h=1,t=2,sta; q[1]=S; layer[S]=0; while(h<t) { sta=q[h++]; for(int i=head[sta];~i;i=next[i]) if(len[i]&&layer[to[i]]<0) { layer[to[i]]=layer[sta]+1; q[t++]=to[i]; } } return layer[T]!=-1; } inline int find(int u,int cur_flow) { if(u==T) return cur_flow; int res=0,tmp; for(int i=head[u];~i&&res<cur_flow;i=next[i]) if(len[i]&&layer[to[i]]==layer[u]+1) { tmp=find(to[i],min(cur_flow-res,len[i])); len[i]-=tmp; len[i^1]+=tmp; res+=tmp; } if(!res) layer[u]=-1; return res; } inline void go() { int ans=0,num=0; while(bfs()) ans+=find(S,INF); if(!ans) { puts("0"); return; } for(int i=1,res;i<=n;i++) if(i!=ss&&i!=tt) { res=0; rebuild(i); while(bfs()) res+=find(S,INF); if(ans>res) vis[i]=true,num++,ans=res; } printf("%d\n",num); for(int i=1,sg=0;i<=n;i++) if(vis[i]) { if(!sg) sg=true,printf("%d",i); else printf(" %d",i); } puts(""); } int main() { while(scanf("%d%d%d",&n,&ss,&tt)!=EOF) { if(!read()) puts("NO ANSWER!"); else go(); } return 0; }
相关文章推荐
- poj 1815(最小割 + 枚举)
- poj 1815 Friendship【最小割】
- POJ 1815 Friendship 最小割
- [最小点割集]poj 1815 #贪心枚举
- POJ 1815 - Friendship 求最小割点..要求字典序...枚举+最小割
- POJ 1815 Friendship(最小割)
- poj 1815 Friendship(最小点割集)
- poj1815 无向图点的最小割
- Poj 1815 Friendship 枚举+求最小割
- POJ 1815 Friendship 最小割 + 字典序输出割点
- poj 1815 最小点割转化为最小边割+枚举 (邻接矩阵+递归dinic)
- poj 1815 Friendship 字典序最小+最小割
- POJ 1815 Friendship (最小点割集)
- POJ 1815 最小割 拆点 枚举
- poj 1815 Friendship(最小割,求割集)
- POJ 1815 - Friendship(网络流‘最小割)
- poj 1815 Friendship (最小割+拆点+枚举)
- poj 1815(最小割、割集)
- poj 1815 Friendship 最小割输出最小方案
- poj--1815--Friendship(最小割点集)(枚举求最小字典序)