• UVA10480 Sabotage


    题目链接:https://cn.vjudge.net/problem/UVA-10480

    知识点:  最小割

    题目大意:

      求最小割并打印出最小割必须割掉的边。

    解题思路:

      在跑完 (sap) 后的残量网络上,记录源点和汇点可达的点,然后遍历所有的边(设边的两端点为 (u) 和 (v)),如果 (u) 源点可达而 (v) 汇点可达(或与之相反,(v) 源点可达而 (u) 汇点可达),则说明该边必须割。

    AC代码:

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 const int MAXN=52;
      5 const int MAXM=1010;
      6 const int INF=0x3f3f3f3f;
      7 struct Edge{
      8     int from,to,Next,cap,flow;
      9 }edge[MAXM];
     10 int flag[MAXN];
     11 int tol;
     12 int head[MAXN];
     13 int gap[MAXN],dep[MAXN],cur[MAXN];
     14 void init(){
     15     tol=0;
     16     memset(flag,0,sizeof(flag));
     17     memset(head,-1,sizeof(head));
     18 }
     19 void addedge(int u,int v,int w,int rw){
     20     edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0;
     21     edge[tol].Next=head[u]; head[u]=tol++;
     22     edge[tol].from=v; edge[tol].to=u; edge[tol].cap=rw; edge[tol].flow=0;
     23     edge[tol].Next=head[v]; head[v]=tol++;
     24 }
     25 int Q[MAXN];
     26 void BFS(int start,int ends){
     27     memset(dep,-1,sizeof(dep));
     28     memset(gap,0,sizeof(gap));
     29     gap[0]=1;
     30     int fronts=0,rear=0;
     31     dep[ends]=0;
     32     Q[rear++]=ends;
     33     while(fronts!=rear){
     34         int u=Q[fronts++];
     35         for(int i=head[u];i!=-1;i=edge[i].Next){
     36             int v=edge[i].to;
     37             if(dep[v]!=-1)  continue;
     38             Q[rear++]=v;
     39             dep[v]=dep[u]+1;
     40             gap[dep[v]]++;
     41         }
     42     }
     43 }
     44 int S[MAXN];
     45 int sap(int start,int ends,int N){
     46     BFS(start,ends);
     47     memcpy(cur,head,sizeof(head));
     48     int top=0;
     49     int u=start;
     50     int ans=0;
     51     while(dep[start]<N){
     52         if(u==ends){
     53             int Min=INF;
     54             int inser;
     55             for(int i=0;i<top;i++){
     56                 if(Min>edge[S[i]].cap-edge[S[i]].flow){
     57                     Min=edge[S[i]].cap-edge[S[i]].flow;
     58                     inser=i;
     59                 }
     60             }
     61             for(int i=0;i<top;i++){
     62                 edge[S[i]].flow+=Min;
     63                 edge[S[i]^1].flow-=Min;
     64             }
     65             ans+=Min;
     66             top=inser;
     67             u=edge[S[top]^1].to;
     68             continue;
     69         }
     70         bool flag=false;
     71         int v;
     72         for(int i=cur[u];i!=-1;i=edge[i].Next){
     73             v=edge[i].to;
     74             if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]){
     75                 flag=true;
     76                 cur[u]=i;
     77                 break;
     78             }
     79         }
     80         if(flag){
     81             S[top++]=cur[u];
     82             u=v;
     83             continue;
     84         }
     85         int Min=N;
     86         for(int i=head[u];i!=-1;i=edge[i].Next){
     87             if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min){
     88                 Min=dep[edge[i].to];
     89                 cur[u]=i;
     90             }
     91         }
     92         gap[dep[u]]--;
     93         if(!gap[dep[u]])    return ans;
     94         dep[u]=Min+1;
     95         gap[dep[u]]++;
     96         if(u!=start)    u=edge[S[--top]^1].to;
     97     }
     98     return ans;
     99 }
    100 void dfs(int x,int od){
    101     flag[x]=od;
    102     for(int i=head[x];i!=-1;i=edge[i].Next){
    103         if(edge[i].flow==edge[i].cap)   continue;
    104         if(!flag[edge[i].to])
    105             dfs(edge[i].to,od);
    106     }
    107 }
    108 int main(){
    109 //    freopen("in.txt","r",stdin);
    110 //    freopen("out.txt","w",stdout);
    111     int n,m;
    112     while(scanf("%d%d",&n,&m)==2&&n){
    113         init();
    114         int u,v,w;
    115         for(int i=0;i<m;i++){
    116             scanf("%d%d%d",&u,&v,&w);
    117             addedge(u,v,w,w);
    118         }
    119         sap(1,2,n);
    120         dfs(1,1);
    121         dfs(2,2);
    122         for(int i=0;i<tol;i+=2){
    123             int u=edge[i].from,v=edge[i].to;
    124             if((flag[u]==1&&flag[v]==2)||(flag[u]==2&&flag[v]==1))
    125                 printf("%d %d
    ",u,v);
    126         }
    127         printf("
    ");
    128     }
    129     return 0;
    130 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    zookeeper与activemq最新存储replicatedLevelDB整合
    MySQL分表的3种方法
    mycat 从入门到放弃 (转)
    centos 7 忘记密码
    java内存溢出的情况解决方法
    跨域问题的产生及解决方法
    一次jvm调优过程
    2019年总结
    Jenkinsfile与Json的转换
    DevOps平台
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9250326.html
Copyright © 2020-2023  润新知