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 }
View Code

 

0 0
原创粉丝点击