POJ 1815 求最小点割(拆点+枚举割边)
2012-06-14 19:46
253 查看
题目链接: http://poj.org/problem?id=1815
题目大意:
给定n个人的关系,a,b互相有联系,b,c也互相有联系的话那么a,c也互相有联系(满足传递性),然后给定一个S,T,问最少需要删除多少个人使得S与T没有联系,如果有多种方案,输出字典序最小的。
分析:
我直接百度的。
这道题就是一个求源和汇点联通度的题,转换过来就是最大流最小割问题,把求点割转换到边割。
http://hi.baidu.com/zfy0701/blog/item/a521f230b06dea9fa9018e0e.html
我的代码还是根据枚举点,使得它不与其他点相连,求最大流看与初始流比较是否减少来判断该点是否属于最小割。更方便的做法还不会,另外fhq在discuss里说了一个很神奇的方法,看不懂。
代码:
poj1815
题目大意:
给定n个人的关系,a,b互相有联系,b,c也互相有联系的话那么a,c也互相有联系(满足传递性),然后给定一个S,T,问最少需要删除多少个人使得S与T没有联系,如果有多种方案,输出字典序最小的。
分析:
我直接百度的。
这道题就是一个求源和汇点联通度的题,转换过来就是最大流最小割问题,把求点割转换到边割。
http://hi.baidu.com/zfy0701/blog/item/a521f230b06dea9fa9018e0e.html
我的代码还是根据枚举点,使得它不与其他点相连,求最大流看与初始流比较是否减少来判断该点是否属于最小割。更方便的做法还不会,另外fhq在discuss里说了一个很神奇的方法,看不懂。
代码:
poj1815
/*1815 Accepted 640K 782MS C++ 3965B 2012-06-14 17:35:11*/ #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <vector> using namespace std; #define mpair make_pair #define pii pair<int,int> #define MM(a,b) memset(a,b,sizeof(a)); typedef long long lld; typedef unsigned long long u64; template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;} template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;} #define maxn 410 #define maxm 20010 const int inf= 2100000000; int n,m,S,T; int ST, ED, NV; int map[maxn][maxn]; int dis[maxn], pre[maxn], gap[maxn], cur[maxn]; int top, head[maxn]; struct Edge{ int v,w,next; Edge(){} Edge(int v,int w,int next): v(v), w(w), next(next){} }edge[maxm]; void Addedge(int u,int v,int w){ edge[top]= Edge( v, w, head[u] ); head[u]= top++; edge[top]= Edge( u, 0, head[v] ); head[v]= top++; } int sap(){ int maxflow= 0; for(int i=0;i<NV;++i) dis[i]= gap[i]= 0, cur[i]= head[i]; int u= pre[ST]= ST; int v, aug= inf; gap[0]= NV; while( dis[ST]<NV ){ for(int &i= cur[u]; i!=-1; i=edge[i].next){ v= edge[i].v; if( edge[i].w && dis[u]==dis[v]+1 ) break; } if( -1 != cur[u] ){ up_min( aug, edge[ cur[u] ].w ); pre[v]= u; u= v; if( v==ED ){ maxflow+= aug; for(u=pre[u];v!=ST;v=u,u=pre[u]){ edge[ cur[u] ].w-= aug; edge[ cur[u]^1 ].w+= aug; } aug= inf; } } else{ int mindis= NV; for(int i=head[u]; i!=-1; i= edge[i].next){ int v= edge[i].v; if( edge[i].w && up_min( mindis, dis[v] ) ) cur[u]= i; } if( --gap[ dis[u] ] == 0 ) break; ++gap[ dis[u]= mindis+1 ]; u= pre[u]; } } return maxflow; } void Init_graph(){ top= 0; MM( head, -1 ); ST= 0, ED= n+n+1; NV= n+n+2; /// Addedge( ST, S, inf ); Addedge( T+n, ED, inf ); for(int i=1;i<=n;++i){ if( i==S || i==T ) Addedge( i, i+n, inf ); else Addedge( i, i+n, 1 ); } for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if( map[i][j] && i!=j ) /// i!=j; Addedge( i+n, j, inf ); } bool mark[maxn]; void Rebuild_graph(int v){ top= 0; MM( head, -1 ); /// ST= 0, ED= n+n+1, NV= n+n+2; Addedge( ST, S, inf ); Addedge( T+n, ED, inf ); for(int i=1;i<=n;++i){ if( i==S || i==T ) Addedge( i, i+n, inf ); else if( i!=v && !mark[i] ) Addedge( i, i+n, 1 ); } for(int i=1;i<=n;++i){ if( i==v || mark[i] ) continue; for(int j=1;j<=n;++j) if( map[i][j] && i!=j && j!=v && !mark[j] ) Addedge( i+n, j, inf ); } } int main() { //freopen("poj1815.in","r",stdin); while( cin>>n>>S>>T ){ for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d", &map[i][j]); if( map[S][T]==1 ){ puts("NO ANSWER!"); continue; } Init_graph(); int Flow= sap(); if( 0==Flow ){ puts("0"); continue; } fill( mark, mark+1+n, 0 ); int cnt= 0; for(int i=1;i<=n;++i){ if( i==S || i==T ) continue; Rebuild_graph( i ); int tmp= sap(); if( up_min( Flow, tmp ) ){ ++cnt; mark[i]= 1; } } /// output the answer; printf("%d\n", cnt); bool flag= 0; for(int i=1;i<=n;++i){ if( mark[i] ){ if( flag ) printf(" "); else flag= 1; printf("%d", i); } } puts(""); } }
相关文章推荐
- POJ 1815 - Friendship 求最小割点..要求字典序...枚举+最小割
- POJ 1815 最小割 拆点 枚举
- poj--1815--Friendship(最小割点集)(枚举求最小字典序)
- POJ 1815 最大流最小割枚举找割点
- poj 1815 Friendship (最小割+拆点+枚举)
- [最小点割集]poj 1815 #贪心枚举
- 【最小割+枚举】POJ-1815 Friendship
- poj 1815 最小点割转化为最小边割+枚举 (邻接矩阵+递归dinic)
- Friendship (poj 1815 最小点割集+枚举)
- poj 1815 Friendship (最小割+拆点+枚举)
- poj 1815(最小割+枚举)
- poj 1815 Friendship 【最小割点集】【枚举删点 + 求解最小字典序】
- poj 1815(最小割 + 枚举)
- Poj 1815 Friendship 枚举+求最小割
- POJ 1753 Flip Game (高斯消元 枚举自由变元求最小步数)
- HDU&POJ 1598 find the most comfortable road(枚举+最小生成树)
- Poj(2784),二进制枚举最小生成树
- POJ 1815 Friendship 最小割
- poj 1815(最小割 割集)
- POJ 1815 Friendship 最小割+字典序最小割集