hdu 4289 dinic模板

题意:有N个城市,现在城市S出现了一伙歹徒,他们想运送一些炸弹到D城市,不过警方已经得到了线报知道他们的事情,不过警察不知道他们所在的具体位置,所以只能采取封锁城市的办法来阻断暴徒,不过封锁城市是需要花费一定代价的,由于警局资金比较紧张,所以想知道如果完全阻断暴徒从S城市到达D城市的最小需要花费的代价。

思路:将每个点都拆分成2个,表示为i和i*,i是原来的起点,然后i到i*的权值为i点原来的权值,连边的时候要注意的是要从i*连接i,因为最初在起点的时候,首先要走的就是从i到i*,然后接下来一定是从i*出发回到i这一边,假设是j,然后j走j*,这样循环往复,所以边的方向都应该是i*到i。

  1 #include<cstdio>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<math.h>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=1000;
  8 const int inf=0x3f3f3f3f;
  9 int head[maxn],level[maxn];
 10 int num;
 11 void init()
 12 {
 13     num=-1  ;
 14     memset(head,-1,sizeof(head));
 15 }
 16 struct node
 17 {
 18     int v,w,next;
 19 }G[400000];
 20 int bfs(int s,int t)
 21 {
 22     queue<int>q;
 23     q.push(s);
 24     memset(level,-1,sizeof(level));
 25     level[s]=0;
 26     while(!q.empty()){
 27         int u=q.front();
 28         q.pop();
 29         for(int i=head[u];i!=-1;i=G[i].next){
 30             int v=G[i].v;
 31             if(G[i].w>0&&level[v]==-1){
 32                 level[v]=level[u]+1;
 33                 q.push(v);
 34             }
 35         }
 36     }
 37    return level[t];
 38 }
 39 int dfs(int s,int t,int f)
 40 {
 41     if(s==t) return f;
 42     int ans=0;
 43     for(int i=head[s];i!=-1;i=G[i].next){
 44         int v=G[i].v;
 45         if(G[i].w>0&&level[s]+1==level[v]){
 46             int d=dfs(v,t,min(G[i].w,f-ans));
 47             if(d>0){
 48                 G[i].w-=d;
 49                 G[i^1].w+=d;
 50                 ans+=d;
 51                 if(ans==f) return ans;
 52             }
 53         }
 54     }
 55     return ans;
 56 }
 57 int dinic(int s,int t)
 58 {
 59     int ans=0;
 60     while(1){
 61         int temp=bfs(s,t);
 62         if(temp==-1) break;
 63         ans+=dfs(s,t,inf);
 64     }
 65     return ans;
 66 }
 67 void build(int u,int v,int w)
 68 {
 69     num++;
 70     G[num].v=v;
 71     G[num].w=w;
 72     G[num].next=head[u];
 73     head[u]=num;
 74 
 75     num++;
 76     G[num].v=u;
 77     G[num].w=0;
 78     G[num].next=head[v];
 79     head[v]=num;
 80 }
 81 int main()
 82 {
 83     int n,m;
 84     while(scanf("%d%d",&n,&m)!=EOF){
 85         init();
 86         int s,t;
 87         scanf("%d%d",&s,&t);
 88         t=t+n;
 89         int temp;
 90         for(int i=1;i<=n;i++){
 91             scanf("%d",&temp);
 92             build(i,i+n,temp);
 93         }
 94         for(int i=1;i<=m;i++){
 95             int u;int v;
 96             scanf("%d%d",&u,&v);
 97             build(u+n,v,inf);
 98             build(v+n,u,inf);
 99         }
100         printf("%d\n",dinic(s,t));
101     }
102     return 0;
103 }

 

转载于:https://www.cnblogs.com/pangbi/p/11580279.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值