• D 勤奋的杨老师(二)(最小割)


    显然是最小割的经典应用“二者选一”

    这里有一个用其他算法不好解决的地方,选择了v,则必须选择所有的u,而对于这个直接建好v指向u的边,容量设为正无穷即可。(即该边不可被割)

    源点指向某个知识点,边容量为收益大小,这个点再指向汇点,边容量为损失大小。

    对于每个点,要么选(切断与汇点的联系),要么不选(切断与源点的联系),用链接源点的收益和减去最小割就是答案。

    最小割的巨大优势是,它可以同时考虑所有点的选择,而得出最优解。

    最小割==最大流

    最小割:将原图割成只与源点相连和只与汇点相连的两个集合,需要割掉的最小边权和

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<map>
      8 using namespace std;
      9 typedef  long long ll;
     10 const int MAX_N = 1600;  
     11 const int MAX_M = 50000;  
     12 const int INF = 1000000000;  
     13 struct edge {
     14     int v, c, next;   
     15 } e[MAX_M];
     16 int p[MAX_N], eid;
     17 void init() {
     18     memset(p, -1, sizeof(p));
     19     eid = 0;
     20 }
     21 void insert(int u, int v, int c) {  
     22     e[eid].v = v;
     23     e[eid].c = c;
     24     e[eid].next = p[u];
     25     p[u] = eid++;
     26 }
     27 void addedge(int u, int v, int c) {  
     28     insert(u, v, c);
     29     insert(v, u, 0);  
     30 }
     31 int S, T;  
     32 int d[MAX_N];  
     33 bool CountLayer() {  
     34     memset(d, -1, sizeof(d));
     35     queue<int> q;
     36     q.push(S);
     37     d[S] = 0;
     38     while (!q.empty()) {
     39         int u = q.front();
     40         q.pop();
     41         for (int i = p[u]; i != -1; i = e[i].next) {
     42             int v = e[i].v;
     43             if (e[i].c > 0 && d[v] == -1) {
     44                 q.push(v);
     45                 d[v] = d[u] + 1;
     46             }
     47         }
     48     }
     49     return (d[T] != -1);  
     50 }
     51 
     52 ll dfs(int u, int flow) {  
     53     if (u == T) {
     54         return flow;
     55     }
     56     ll res = 0;
     57     for (int i = p[u]; i != -1; i = e[i].next) {
     58         int v = e[i].v;
     59         if (e[i].c > 0 && d[u] + 1 == d[v]) {
     60             ll tmp = dfs(v, min(flow, e[i].c));  
     61             flow -= tmp;
     62             e[i].c -= tmp;
     63             res += tmp;
     64             e[i ^ 1].c += tmp;  
     65             if (flow == 0) {  
     66                 break;
     67             }
     68         }
     69     }
     70     if (res == 0) {  
     71         d[u] = -1;
     72     }
     73     return res;
     74 }
     75 
     76 ll maxflow() {  
     77     ll res = 0;
     78     while (CountLayer()) {
     79         res += dfs(S, INF);  
     80     }
     81     return res;
     82 }
     83 
     84 int main()
     85 {    int n;
     86     cin>>n;
     87     ll x,y,sum=0;
     88     S=0,T=n+1;
     89     init();
     90     for(int i=1;i<=n;i++)
     91     {    
     92         cin>>x>>y;
     93         int res=x-y;
     94         if(res>0) addedge(0, i, res),sum+=res;
     95         
     96         else addedge(i, n+1, -res);
     97         
     98     }
     99     while(~scanf("%d%d",&x,&y))
    100     {
    101         addedge(y, x, INF);
    102     }
    103     cout<<sum-maxflow()<<endl;
    104     
    105     return 0;
    106 } 
    View Code

  • 相关阅读:
    FIREDAC操作SQLITE内存数据库
    DELPHI移动端支付宝支付
    DELPHI支付宝支付代码
    DELPHI微信支付代码
    mssql内存表
    Ubuntu下添加开机启动项的2种方法
    docker容器中安装vim
    使用find命令查找Linux中的隐藏文件的方法
    Go语言_RPC_Go语言的RPC
    Mac下export生效
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/9004506.html
Copyright © 2020-2023  润新知