poj 1815(最小割、割集)
来源:互联网 发布:中国博士数量 知乎 编辑:程序博客网 时间:2024/04/27 15:54
题目链接:http://poj.org/problem?id=1815
思路:题目要求是剔除多少个点,可以将其转化为剔除多少条边,因此需要拆点,将点i拆成i,i+n,便容量为1,表示每个人起的传递作用只能是一次。然后就是枚举了,删除某条边,如果求出的最小割比原来的要小,说明减少的是割边集。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define MAXN 444 8 #define MAXM 4444444 9 #define inf 1<<30 10 11 struct Edge{ 12 int v,cap,next; 13 }edge[MAXM]; 14 15 int n,vs,vt,NE,NV; 16 int head[MAXN]; 17 18 void Insert(int u,int v,int cap) 19 { 20 edge[NE].v=v; 21 edge[NE].cap=cap; 22 edge[NE].next=head[u]; 23 head[u]=NE++; 24 25 edge[NE].v=u; 26 edge[NE].cap=0; 27 edge[NE].next=head[v]; 28 head[v]=NE++; 29 } 30 31 int level[MAXN],gap[MAXN]; 32 void bfs(int vt) 33 { 34 memset(level,-1,sizeof(level)); 35 memset(gap,0,sizeof(gap)); 36 level[vt]=0; 37 gap[level[vt]]++; 38 queue<int>que; 39 que.push(vt); 40 while(!que.empty()){ 41 int u=que.front(); 42 que.pop(); 43 for(int i=head[u];i!=-1;i=edge[i].next){ 44 int v=edge[i].v; 45 if(level[v]!=-1)continue; 46 level[v]=level[u]+1; 47 gap[level[v]]++; 48 que.push(v); 49 } 50 } 51 } 52 53 int pre[MAXN],cur[MAXN]; 54 int SAP(int vs,int vt) 55 { 56 bfs(vt); 57 memset(pre,-1,sizeof(pre)); 58 memcpy(cur,head,sizeof(head)); 59 int maxflow=0,aug=inf; 60 int u=pre[vs]=vs; 61 gap[0]=NV; 62 while(level[vs]<NV){ 63 bool flag=false; 64 for(int &i=cur[u];i!=-1;i=edge[i].next){ 65 int v=edge[i].v; 66 if(edge[i].cap>0&&level[u]==level[v]+1){ 67 flag=true; 68 pre[v]=u; 69 u=v; 70 aug=min(aug,edge[i].cap); 71 if(v==vt){ 72 maxflow+=aug; 73 for(u=pre[v];v!=vs;v=u,u=pre[u]){ 74 edge[cur[u]].cap-=aug; 75 edge[cur[u]^1].cap+=aug; 76 } 77 aug=inf; 78 } 79 break; 80 } 81 } 82 if(flag)continue; 83 int minlevel=NV; 84 for(int i=head[u];i!=-1;i=edge[i].next){ 85 int v=edge[i].v; 86 if(edge[i].cap>0&&level[v]<minlevel){ 87 minlevel=level[v]; 88 cur[u]=i; 89 } 90 } 91 if(--gap[level[u]]==0)break; 92 level[u]=minlevel+1; 93 gap[level[u]]++; 94 u=pre[u]; 95 } 96 return maxflow; 97 } 98 99 int map[MAXN][MAXN];100 int cut[MAXN];101 void Build()102 {103 NE=0;104 memset(head,-1,sizeof(head));105 for(int i=1;i<=n;i++){106 if(cut[i])continue;107 for(int j=1;j<=n;j++){108 if(cut[j])continue;109 if(i==j)Insert(i,i+n,1);110 else if(map[i][j])Insert(i+n,j,inf);111 }112 }113 }114 115 int main()116 {117 int maxflow,ans;118 while(~scanf("%d%d%d",&n,&vs,&vt)){119 for(int i=1;i<=n;i++)120 for(int j=1;j<=n;j++)121 scanf("%d",&map[i][j]);122 if(map[vs][vt]){123 puts("NO ANSWER!");124 continue;125 }126 vs+=n,NV=2*n;127 memset(cut,0,sizeof(cut));128 Build();129 maxflow=SAP(vs,vt);130 ans=0;131 for(int i=1;i<=n;i++){132 if(maxflow==0)break;133 if(i==(vs-n)||i==vt)continue;134 cut[i]=1;135 Build();136 int tmp=SAP(vs,vt);137 if(tmp<maxflow){ ans++,maxflow=tmp; }138 else cut[i]=0;139 }140 printf("%d\n",ans);141 bool flag=true;142 for(int i=1;i<=n;i++){143 if(cut[i]){144 printf(flag?"%d":" %d",i);145 flag=false;146 }147 }148 puts("");149 }150 return 0;151 }
0 0
- poj 1815(最小割、割集)
- POJ 1815 Friendship 最小割+字典序最小割集
- POJ 1815 (最小割的点集)
- POJ 1815 Friendship(最小割)
- POJ 1815 Friendship(最小割+拆点法)
- poj 1815 Friendship //最小割
- 【unsolved最小割】POJ 1815
- poj 1815(最小割+枚举)
- POJ 1815 Friendship 最小割
- POJ 1815 Friendship(最小割)
- POJ 1815 Friendship 最小割
- POJ 1815 Friendship 最小割
- poj 3469(最小割)
- poj 3204(最小割)
- poj 3084(最小割)
- poj 2125(最小割)
- poj 3469(最小割)
- 3469poj(最小割)
- poj 3310(并查集判环,图的连通性,树上最长直径路径标记)
- poj 3653(最短路)
- poj 1659(havel算法)
- poj 2914(stoer_wanger算法求全局最小割)
- poj 3249(bfs+dp或者记忆化搜索)
- poj 1815(最小割、割集)
- poj 1966(求点连通度,边连通度的一类方法)
- poj 3084(最小割)
- poj 3498(最大流+拆点)
- hdu 4597(记忆化搜索)
- poj 3422(最小费用最大流)
- poj 3680(最小费用最大流)
- poj 1419(图的着色问题,搜索)
- hdu 4289(最小割)