• hdu6808 Go Running // dinic 网络流


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6808

    网络流之第一次遇见你 ——>基本厚脸皮照搬

    感谢HY大佬及参考文献の指点

    尽可能写了一点注释方便理解

    参考文献:https://blog.csdn.net/weixin_43828245/article/details/107700724

    *转载请附链接 谢谢

      1 #include<iostream>
      2 #include<queue>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<iomanip>
      6 #include<cstdio>
      7 #include<cmath>
      8 #include<cstring>
      9 
     10 #define INF 2e9
     11 const int maxn = 2e6 + 10;
     12 using namespace std;
     13 
     14 typedef struct point
     15 {
     16     int flow;
     17     int to;
     18     int next;
     19     point(int a = 0, int b = 0, int c = 0){flow = a, to = b, next = c;} 
     20 } node;
     21 
     22 int n, cnt;
     23 int s, t;//源/汇点
     24 int a[maxn], b[maxn];
     25 int da[maxn], db[maxn];
     26 int head[maxn];//x元素在N数组中的下标即为head[x] 
     27 node N[maxn];
     28 
     29 int deep[maxn];//各点深度 
     30 int hhead[maxn];//dfs中更新headの复制品 
     31 
     32 void Add_Edge(int i, int j, int val)
     33 {
     34     N[cnt].flow = val;
     35     N[cnt].to = j;
     36     N[cnt].next = head[i];
     37     head[i] = cnt++;//从零开始,自增为后缀 
     38 }
     39 
     40 int BFS(int x)//分层网络 
     41 {
     42     memset(deep, 0, sizeof(deep));//除源点外其余点深度为0 
     43     memcpy(hhead, head ,sizeof(hhead));
     44     deep[x] = 1;//源点深度为1
     45     queue<int> q;
     46     q.push(x);
     47     while(!q.empty()){
     48         int now = q.front();//取出队首元素后弹出 
     49         q.pop();
     50         for(int i = head[now] ; i != -1 ; i = N[i].next){//从now节点开始访问 
     51             int nxt = N[i].to, f = N[i].flow;
     52             if(!deep[nxt] && f > 0){//下一点未访问且流量可调整 
     53                 deep[nxt] = deep[now] + 1;
     54                 q.push(nxt);
     55             }
     56         }
     57     }
     58     return deep[t];//汇点若深度为0,则无路可走 
     59 }
     60 
     61 int dfs(int x, int val)//找增广路
     62 {
     63     if(x == t)    return val;
     64     int sum = 0;
     65 
     66     for(int i = hhead[x] ; i != -1 ; i = N[i].next){
     67         hhead[x] = i;
     68         int nxt = N[i].to, f = N[i].flow;
     69         if(f > 0 && deep[nxt] == deep[x] + 1){
     70             int t = dfs(nxt ,min(val - sum, f));//
     71             sum += t;
     72             N[i].flow -= t;
     73             N[i ^ 1].flow += t;//见107行 
     74             if(sum == val)    break;//管道满了 
     75         }
     76     }
     77     
     78     if(sum == 0){//*如果sum==0,那么这个点之前没有增广路,深度清零
     79         deep[x] = 0;
     80     }
     81     return sum;
     82 }
     83 
     84 int main(){
     85     
     86     int T;cin >> T;
     87     while(T--)
     88     {
     89         cin >> n;
     90         memset(head, -1, sizeof(head));//读head数组,直到-1则无路,返回//因而初始化为-1 
     91         cnt = 0;
     92         
     93         int cnta = 0, cntb = 0;
     94         for(int i = 0 ; i < n ; i++){
     95             int t, x;
     96             cin >> t >> x;        
     97             da[i] = a[i] = x - t;
     98             db[i] = b[i] = x + t;            
     99         }
    100         //排序(方便lower_bound)+去重
    101         sort(da, da + n);
    102         cnta = unique(da, da + n) - da;
    103         sort(db, db + n);
    104         cntb = unique(db, db + n) - db;
    105         
    106         s = cnta + cntb + 5; t = s + 1;//源点/汇点 
    107         //加边时成对进行,因而正反两边的编号也相邻,为了满足异或运算,编号必须从偶数开始
    108         /*
    109         0 ^ 1 = 1
    110         1 ^ 1 = 0
    111         2 ^ 1 = 3
    112         3 ^ 1 = 2
    113         ...
    114         */
    115         for(int i = 0 ; i < n ; i++){
    116             int pos1 = lower_bound(da, da + cnta, a[i]) - da;
    117             int pos2 = lower_bound(db, db + cntb, b[i]) - db + cnta + 2;
    118             //确定V集下标 
    119             Add_Edge(pos1, pos2, 1);//U集与V集
    120             Add_Edge(pos2, pos1, 0);
    121         }
    122         
    123         for(int i = 0 ; i < cnta ; i++){
    124             Add_Edge(s, i, 1);//源点与U集 
    125             Add_Edge(i, s, 0);
    126         }
    127         
    128         for(int i = 0 ; i < cntb ; i++){
    129             Add_Edge(i + cnta + 2, t, 1);//汇点与V集 
    130             Add_Edge(t, i + cnta + 2, 0);
    131         }
    132         
    133         int res = 0; 
    134         while(BFS(s)){//源点开搞 
    135             res += dfs(s, INF);
    136         }
    137         cout << res << endl;
    138     }
    139     
    140     return 0;
    141 }
  • 相关阅读:
    唤醒控件曾经拥有的能力(重新继承是可以使用的.)
    为ASP.NET MVC应用程序创建更复杂的数据模型
    Akka入门实例
    最火的.NET开源项目(转)
    Roslyn 编译平台概述
    C#开发157
    ASP.NET MVC学习之控制器篇
    AngularJS中数据双向绑定(two-way data-binding)
    订单系统中并发问题和锁机制的探讨
    Visual Studio 编辑器
  • 原文地址:https://www.cnblogs.com/ecustlegendn324/p/13491298.html
Copyright © 2020-2023  润新知