zoukankan      html  css  js  c++  java
  • 【BZOJ 4663】 (最小割)

    4663: Hack

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 69  Solved: 26

    Description

    由于 FZYZ 教学区禁止使用手机,所以如何在一个课间通知到人就成了一个很大的问题。所幸,在不知道被信息传
    递不及时坑了多少次之后,小叶子(@97littleleaf11)完美地解决了这个问题。小叶子组建了一张关系网,每一个
    人是这张关系网上的一个节点(节点编号为[0,n-1]),两个人之间的通讯关系就是这张网上的一条有向边(一条 u->
    v 的边意味着信息可以从u 传递到 v)。小叶子是 0 号节点,也是信息的发出者,n+e 是 n-1 号节点,在这个问
    题中,他就是信息的接受者。一条信息从小叶子出发,可以沿着任意的边传递,最终传递给 n+e。在这个过程中,
    一个人(包括小叶子和 n+e)可以经过多次,一条边也可以经过多次。经过多年的观察,小叶子发现这张关系网的每
    一条边都是有可能被hack 的!当然每条边 hack 的代价是不一样的。所以,小叶子想要评价这个关系网的安全程
    度。试想你要入侵这一张关系网,那么你只能事先选择一些边,将这些边hack 掉。如果一条边被 hack 了,就意
    味着当信息从这条边传递的时候就会被截获。当然 n+e 也是非常厉害的!如果一条信息在传递过程中被截获两次
    及以上,那么 n+e 就能用强大的智商定位出你的位置,那么这一次入侵就必然会失败。当然,如果 n+e 接收到了
    消息,但是这条消息没有被截获,那么这次入侵也就是失败的。更精确地说,一次成功的入侵要满足以下条件:对
    于任意一种可能的传递信息的方式(对应着一条从 0 到 n-1 的路径),必须经过恰好一次被hack 的边。一次入侵
    的代价就是你选择 hack 掉的边的代价和。小叶子想要知道,如果你拥有 n+e 这样超神的智商,而你又想最小化
    代价,那么你入侵的代价会是多少呢?

    Input

    第一行 n,m。表示点数及边数
    接下来 m 行,每行三个整数 u,v,w,表示一条从 u 到 v 的代价为 w 的边。
    2<=n<=100,m<=2500,1<=w<=10^9,0<=u,v<n,保证存在至少一条从0到n-1的路径。

    Output

    输出一行,表示答案。,如果不存在合法的入侵方案,那么输出-1.

    Sample Input

    6 7
    0 1 5
    0 2 5
    1 3 1
    2 4 1
    4 1 1
    3 5 5
    4 5 5

    Sample Output

    6
    //hack 掉 0->1,2->4 这两条边

    HINT

    Source

    【分析】

      其实反向边建INF的想法有考虑过。但是不会证。很迷人。。。

      送个迷人的图:

      

      就是建了inf反向边,就不会同一路径的割了,因为并不会更好。。

      然后要注意删掉st到不了的点,不然会有这样迷人的情况:

      

      st本来不会经过a到ed,但现在这样建INF,就一定要割掉一些边断掉它了。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<stack>
      8 using namespace std;
      9 #define Maxn 110
     10 #define Maxm 2600
     11 #define LL long long
     12 const LL INF=(LL)3000*(LL)1e9;
     13 
     14 LL mymin(LL x,LL y) {return x<y?x:y;}
     15 
     16 struct node{int x,y,o,next;LL f;bool p;}t[Maxm*2];
     17 bool vis[Maxn];
     18 int first[Maxn],len;
     19 
     20 void ins(int x,int y,LL f)
     21 {
     22     t[++len].x=x;t[len].y=y;t[len].f=f;
     23     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     24     t[++len].x=y;t[len].y=x;t[len].f=INF;
     25     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     26     t[len-1].p=t[len].p=1;
     27 }
     28 
     29 void dfs(int x)
     30 {
     31     vis[x]=1;
     32     for(int i=first[x];i;i=t[i].next)
     33     {
     34         if(i%2==0) continue;
     35         int y=t[i].y;
     36         if(!vis[y]) dfs(y);
     37     }
     38 }
     39 
     40 int st,ed;
     41 int dis[Maxn];
     42 queue<int > q;
     43 bool bfs()
     44 {
     45     for(int i=1;i<=ed;i++) dis[i]=-1;
     46     while(!q.empty()) q.pop();
     47     dis[st]=0;q.push(st);
     48     while(!q.empty())
     49     {
     50         int x=q.front();
     51         for(int i=first[x];i;i=t[i].next) if(t[i].p&&t[i].f>0)
     52         {
     53             int y=t[i].y;
     54             if(!vis[y]) continue;
     55             if(dis[y]==-1)
     56             {
     57                 dis[y]=dis[x]+1;
     58                 q.push(y);
     59             }
     60         }
     61         q.pop();
     62     }
     63     if(dis[ed]==-1) return 0;
     64     return 1;
     65 }
     66 
     67 LL ffind(int x,LL flow)
     68 {
     69     if(x==ed) return flow;
     70     LL now=0;
     71     for(int i=first[x];i;i=t[i].next) if(t[i].p&&t[i].f>0)
     72     {
     73         int y=t[i].y;
     74         if(dis[y]==dis[x]+1)
     75         {
     76             LL a=ffind(y,mymin(flow-now,t[i].f));
     77             t[i].f-=a;
     78             t[t[i].o].f+=a;
     79             now+=a;
     80         }
     81         if(now==flow) break;
     82     }
     83     if(now==0) dis[x]=-1;
     84     return now;
     85 }
     86 
     87 void output()
     88 {
     89     for(int i=1;i<=len;i++) if(t[i].p)
     90     {
     91         printf("%d -> %d %d
    ",t[i].x,t[i].y,t[i].f);
     92     }printf("
    ");
     93 }
     94 
     95 LL ans=0;
     96 void max_flow()
     97 {
     98     while(bfs())
     99     {
    100         ans+=ffind(st,INF);
    101         if(ans>=INF) break;
    102     }
    103 }
    104 
    105 int main()
    106 {
    107     int n,m;
    108     scanf("%d%d",&n,&m);
    109     len=0;
    110     memset(first,0,sizeof(first));
    111     for(int i=1;i<=m;i++)
    112     {
    113         int x,y;LL f;
    114         scanf("%d%d%lld",&x,&y,&f);
    115         x++;y++;
    116         ins(x,y,f);
    117     }
    118     for(int i=1;i<=n;i++) vis[i]=0;vis[1]=1;
    119     dfs(1);
    120     for(int i=1;i<=len;i+=2) if(vis[t[i].x]==0) t[i].p=t[t[i].o].p=0;
    121     st=1;ed=n;
    122     // output();
    123     max_flow();
    124     if(ans>=INF) printf("-1
    ");
    125     else printf("%lld
    ",ans);
    126     return 0;
    127 }
    View Code

    2017-03-31 08:26:56

  • 相关阅读:
    Linux——k8s命令别名修改
    k8s—centos7安装部署NFS服务器和客户端及基于nfs的动态存储storageclass使用总结
    MySQL—用户和权限管控
    MySQL—常用SQL语句整理总结
    Zookeeper——入门介绍(相关原理、安装启动及使用操作)
    SpringBoot——Quartz定时框架的使用详解和总结
    SpringBoot——@Scheduled的自定义周期性线程池解决任务延时执行问题
    Linux—用户新建目录和文件的默认权限设置:umask详解
    设计模式——单例模式详解
    Linux—CPU核数、上下文切换介绍及pidstat等命令详解
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6649501.html
Copyright © 2011-2022 走看看