zoukankan      html  css  js  c++  java
  • POJ1815 Friendship(字典序最小最小割割边集)

    看了题解。当时也觉得用邻接矩阵挺好写的,直接memset;然而邻接矩阵不懂得改,于是就放开那个模板,写了Dinic。。

    方法是,按字典序枚举每一条满流的边,然后令其容量减1,如果最大流改变了,这条边就是属于某个最小割;接下来一直重复下去,直到得到一个割边集,而它自然是字典序最小的。

    我在每次某条边容量减1后都重新计算一遍最大流,简单。。其实我知道是有这么一回事,把边容量减1后可以利用当前求出的最大流来得出新的最大流,这样会快一些,不过我不会。。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define INF (1<<30)
     6 int n,vs,vt,NV,c[444][444],f[444][444],level[444];
     7 bool bfs(){
     8     memset(level,0,sizeof(level));
     9     bool vis[444]={0};
    10     vis[vs]=1;
    11     int que[444],front=0,rear=0;
    12     que[rear++]=vs;
    13     while(front<rear){
    14         int u=que[front++];
    15         for(int v=1; v<=NV; ++v){
    16             if(vis[v] || c[u][v]==f[u][v]) continue;
    17             level[v]=level[u]+1;
    18             vis[v]=1;
    19             que[rear++]=v;
    20         }
    21         
    22     }
    23     return vis[vt+n];
    24 }
    25 int dfs(int u,int s){
    26     if(u==vt+n) return s;
    27     int res=s,tmp;
    28     for(int v=1; v<=NV; ++v){
    29         if(level[v]!=level[u]+1 || c[u][v]==f[u][v]) continue;
    30         tmp=dfs(v,min(s,c[u][v]-f[u][v]));
    31         f[u][v]+=tmp;
    32         f[v][u]-=tmp;
    33         s-=tmp;
    34     }
    35     return res-s;
    36 }
    37 int dinic(){
    38     int res=0;
    39     while(bfs()) res+=dfs(vs,INF);
    40     return res;
    41 }
    42 int main(){
    43     int a;
    44     scanf("%d%d%d",&n,&vs,&vt);
    45     NV=n<<1;
    46     for(int i=1;i<=n;++i){
    47         c[i][i+n]=1;
    48         for(int j=1;j<=n;++j){
    49             scanf("%d",&a);
    50             if(i==j || a==0) continue;
    51             c[i+n][j]=INF;
    52         }
    53     }
    54     c[vs][vs+n]=INF; c[vt][vt+n]=INF;
    55     if(c[vs+n][vt]){
    56         puts("NO ANSWER!");
    57         return 0;
    58     }
    59     int ans=dinic();
    60     printf("%d
    ",ans);
    61     for(int i=1; i<=n&&ans; ++i){
    62         if(i==vs||i==vt || f[i][i+n]==0) continue;
    63         memset(f,0,sizeof(f));
    64         c[i][i+n]=0;
    65         if(dinic()<ans){
    66             --ans;
    67             printf("%d ",i);
    68         }else{
    69             c[i][i+n]=1;
    70         }
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    如何正确使用 Composer 安装 Laravel 扩展包
    sql之left join、right join、inner join的区别
    mysql decimal类型与decimal长度用法详解
    mysql数据库操作
    linux下如何查看某软件是否已安装
    MySQL数据类型和常用字段属性总结
    mysql数据库字段类型的选择原则
    linux shell 指令 诸如-d, -f, -e之类的判断表达式
    常用的Homebrew命令
    windows下安装php5.5的redis扩展
  • 原文地址:https://www.cnblogs.com/WABoss/p/4852365.html
Copyright © 2011-2022 走看看