【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\n",t[i].x,t[i].y,t[i].f);
 92     }printf("\n");
 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\n");
125     else printf("%lld\n",ans);
126     return 0;
127 }
View Code

 

2017-03-31 08:26:56

posted @ 2017-03-31 08:27  konjak魔芋  阅读(850)  评论(0编辑  收藏  举报