• poj 1815(最小割、割集)


    题目链接: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
    ",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
  • 相关阅读:
    1010考试T1
    P5631 最小mex生成树 分治 并查集
    P4366 [Code+#4]最短路 建图 最短路
    P1654 OSU! 期望概率DP
    7.26集训
    7.25集训
    7.23集训
    7.22集训
    7.21test
    7.12test
  • 原文地址:https://www.cnblogs.com/wally/p/3282709.html
Copyright © 2020-2023  润新知