zoukankan      html  css  js  c++  java
  • hdu4940 有上下界的无源可行流判断

    题意:
          给你一个强连通图,然后问你是否可以找到任意满足条件的集合S,S是非空集合,T是S的补集,满足sum(D[i ,j]) <= sum(D[j,i] + B[j,i]) i属于S集合,j属于T集合(其实也就暗示了i,j是S,T的割边)。

    思路:

           无源汇上下流可行流判断问题,首先题目给的图是一个强连通图,为了方便理解,我们假设这个图只有两个点,a,b,那么肯定也只有两条边,a->b ,b->a,那么我们可以直接建边a->b(下界 D 上界 B + D) b->a(下界 D 上界 B + D)这样跑一遍上下流之后如果存在可行流,那么就存在一个a,b之间的循环流(循环流的大小我们不用关心,我们只关心是否存在),那么就会有这样的结论,a->b的D(下限)一定小于等于b->a 的D+B(上限),同时 b->a的D(下限) 一定小于等于a->b的 D+B(上限),所以无论是a,还是b都可以充当S集合。so如果整个图中任意两个集合都这样就显然可以满足题意了。


    #include<stdio.h>
    #include<string.h>
    #include<queue>
    
    #define N_node 220
    #define N_edge 33000
    #define INF 1000000000
    
    using namespace std;
    
    typedef struct
    {
       int to ,next ,cost;
    }STAR;
    
    typedef struct
    {
       int x ,t;
    }DEP;
    
    STAR E[N_edge];
    DEP xin ,tou;
    int list[N_node] ,listt[N_node] ,tot;
    int deep[N_node] ,sum_must;
    
    void add(int a ,int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
       
       E[++tot].to = a;
       E[tot].cost = 0;
       E[tot].next = list[b];
       list[b] = tot;
    }
    
    void ADD(int a ,int b ,int c ,int d ,int ss ,int tt)
    {
       add(a ,b ,d - c);
       add(a ,tt ,c);
       add(ss ,b ,c);
       sum_must += c;
    }
    
    int minn(int x ,int y)
    {
       return x < y ? x : y;
    }
    
    bool BFS_Deep(int s ,int t ,int n)
    {
       xin.x = s ,xin.t = 0;
       queue<DEP>q;
       q.push(xin);
       memset(deep ,255 ,sizeof(deep));
       deep[s] = 0;
       while(!q.empty())
       {
          tou = q.front();
          q.pop();
          for(int k = list[tou.x] ;k ;k = E[k].next)
          {
             xin.x = E[k].to;
             xin.t = tou.t + 1;
             if(deep[xin.x] != -1 || !E[k].cost)
             continue;
             deep[xin.x] = xin.t;
             q.push(xin);
          }
       }
       for(int i = 0 ;i <= n ;i ++)
       listt[i] = list[i];
       return deep[t] != -1;
    }
    
    int DFS_Flow(int s ,int t ,int flow)
    {
       if(s == t) return flow;
       int nowflow = 0;
       for(int k = listt[s] ;k ;k = E[k].next)
       {
          listt[s] = k;
          int to = E[k].to;
          int c = E[k].cost;
          if(deep[to] != deep[s] + 1 || !c)
          continue;
          int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
          nowflow += tmp;
          E[k].cost -= tmp;
          E[k^1].cost += tmp;
          if(nowflow == flow)
          break;
       }
       if(!nowflow) deep[s] = 0;
       return nowflow;
    }
    
    int DINIC(int s ,int t ,int n)
    {
       int ans = 0;
       while(BFS_Deep(s ,t ,n))
       {
          ans += DFS_Flow(s ,t ,INF);
       }
       return ans;
    }
    
    int main ()
    {
       int t ,n ,m ,i ,a ,b ,c ,d ,cas = 1;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d %d" ,&n ,&m);
          int ss = 0 ,tt = n + 1;
          memset(list ,0 ,sizeof(list));
          tot = 1 ,sum_must = 0;
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d %d" ,&a ,&b ,&c ,&d);
             ADD(a ,b ,c ,c + d ,ss ,tt);
          }
          printf("Case #%d: " ,cas ++);
          sum_must == DINIC(ss ,tt ,tt) ? puts("happy") : puts("unhappy");
       }
       return 0;
    }
       
       
    

  • 相关阅读:
    上采样和下采样
    二、决策树算法
    一、实现贝叶斯算法
    Centos7 安装vscode
    Centos安装IDEA
    Centos设置自带中文输入法
    Centos 安装mysql
    Centos,tomcat
    Centos 7 安装JDK
    Centos7 安装rar,unrar,zip,unzip
  • 原文地址:https://www.cnblogs.com/csnd/p/12062862.html
Copyright © 2011-2022 走看看