• hdu 5352 MZL's City 最小费用最大流


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

    题意:M年前有一个国家发生了地震。所有城市和城市之间的路都被摧毁了。现在要重建城市。

    给出一个N表示共有N个城市,M表示大地震发生在M年前,K表示每次最多只能重建K个城市。

    现在从大地震发生的那年开始,每年可以进行一个操作,也就是总共有M个操作。

    1 x表示可以重建和x联通(直接或间接)的城市(包括x本身),每次最多只能重建K个城市

    2 x y 表示修建了一条城市x到城市y的路。

    3操作给出一个p,表示有p条路被摧毁了,然后给出p个x和y表示城市x和y之间的路被摧毁了。

    要求全部操作完成后最多能重建多少个城市(每个城市最多只能被重建一次)

    并且要求输出每次重建城市操作的全部计划的最小字典序。

    样例:

    1
    5 6 2
    2 1 2 
    2 1 3
    1 1
    1 2
    3 1 1 2
    1 2
    表示第一年,修建了城市1和2之间的道路,第二年修建了城市1和3之间的道路。
    所以第三年重建城市的时候,1和2和3都是联通的。但是因为要输出最小字典序,所以第三年不选择重建。即重建了0个城市
    第四年1和2和3还是都联通的,选择重建城市1和城市3.即重建了2个城市
    第五年,城市1和城市2之间的路被摧毁。
    第六年,选择重建城市2,重建来1个城市。
    所以总共重建了3个城市 输出 0 2 1


    思路:
    网络流。
    在原来的基础上增加源点s和汇点t。
    考虑城市,由于每个城市最多只能重建一次,所以以每个城市为点向汇点t连一条边,容量为1,费用为0.
    考虑1操作。由于每次最多只能重建k个城市。所以由源点s向每个1操作连一条边,容量为K。
    因为要最小字典序点方案。所以每次操作,先操作的费用大,后操作的费用小。可以设初始费用为M,然后后面每次-1.
    然后对于每个1操作。再向当前可以重建的城市连一条边,容量为1,费用为0.
    最后求最小费用最大流。方案就是源点向每个1操作连边的流量。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define maxn 1010
      4 const int inf = 0x3f3f3f3f;
      5 struct Edge
      6 {
      7     int from, to, cap, flow, cost;
      8     Edge(int f, int t, int ca, int fl, int co)
      9     {
     10         from = f; to = t; cap = ca; flow = fl; cost = co;
     11     }
     12 };
     13 vector <Edge> edges;
     14 vector <int> G[maxn];
     15 int n, m, s, t;
     16 int d[maxn], p[maxn], a[maxn], inq[maxn];
     17 void AddEdge(int from, int to, int cap, int cost)
     18 {
     19     edges.push_back(Edge(from, to, cap, 0, cost));
     20     edges.push_back(Edge(to, from, 0, 0, -cost));
     21     m = edges.size();
     22     G[from].push_back(m-2);
     23     G[to].push_back(m-1);
     24 }
     25 bool BellmanFord(int s, int t, int &flow, int &cost)
     26 {
     27     for(int i = 0; i <= n; i++) d[i] = inf;
     28     memset(inq, 0, sizeof(inq));
     29     d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf;
     30 
     31     queue<int> q;
     32     q.push(s);
     33     while(!q.empty())
     34     {
     35         int u = q.front(); q.pop();
     36         inq[u] = 0;
     37         for(int i = 0; i < G[u].size(); i++)
     38         {
     39             Edge &e = edges[G[u][i]];
     40             if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
     41             {
     42                 d[e.to] = d[u] + e.cost;
     43                 p[e.to] = G[u][i];
     44                 a[e.to] = min(a[u], e.cap - e.flow);
     45                 if(!inq[e.to])
     46                 {
     47                     q.push(e.to); inq[e.to] = 1;
     48                 }
     49             }
     50         }
     51     }
     52     if(d[t] == inf) return false;
     53     flow += a[t];
     54     cost += d[t]*a[t];
     55     int u = t;
     56     while(u!=s)
     57     {
     58         edges[p[u]].flow += a[t];
     59         edges[p[u]^1].flow -= a[t];
     60         u = edges[p[u]].from;
     61     }
     62     return true;
     63 }
     64 int flow = 0;
     65 int Mincost()
     66 {
     67     int cost = 0;
     68     while(BellmanFord(s, t, flow, cost));
     69     return cost;
     70 }
     71 int T, N, M, K;
     72 int mp[220][220];
     73 vector <int> connect;
     74 int vis[maxn];
     75 void dfs(int s)
     76 {
     77     for(int i = 1; i <= N; i++)
     78     {
     79         if(mp[s][i] == 1 && !vis[i])
     80         {
     81             connect.push_back(i);
     82             vis[i] = 1;
     83             dfs(i);
     84         }
     85     }
     86     return;
     87 }
     88 int main()
     89 {
     90     scanf("%d", &T);
     91     while(T--)
     92     {
     93         scanf("%d%d%d", &N, &M, &K);
     94         edges.clear();
     95         for(int i = 0; i <= N+M+1; i++) G[i].clear();
     96         memset(mp, 0, sizeof(mp));
     97         s = 0; t = N+M+1; n = N+M+1;
     98         for(int i = 1; i <= N; i++)
     99         {    
    100             mp[i][i] = 1; AddEdge(M+i, t, 1, 0);
    101         }
    102         int initcost = M, op, a, b, cnt = 0;
    103         for(int i = 1; i <= M; i++)
    104         {
    105             scanf("%d", &op);
    106             if(op == 1)
    107             {
    108                 cnt++;
    109                 AddEdge(s, cnt, K, initcost);
    110                 initcost--;
    111                 scanf("%d", &a);
    112                 connect.clear();
    113                 memset(vis, 0, sizeof(vis));
    114                 dfs(a);
    115                 for(int j = 0; j < connect.size(); j++)
    116                 {
    117                     AddEdge(cnt, M+connect[j], 1, 0);
    118                 }
    119             }
    120             else if(op == 2)
    121             {
    122                 scanf("%d%d", &a, &b);
    123                 mp[a][b] = mp[b][a] = 1;
    124             }
    125             else if(op == 3)
    126             {
    127                 int p; scanf("%d", &p);
    128                 while(p--)
    129                 {
    130                     scanf("%d%d", &a, &b);
    131                     mp[a][b] = mp[b][a] = 0;
    132                 }
    133             }
    134         }
    135         flow = 0;
    136         int cost = Mincost();
    137         printf("%d
    ", flow);
    138         bool flag = true;
    139         for(int i = 0; i < m; i += 2)
    140         {
    141             if(edges[i].from == s)
    142             {
    143                 if(flag) printf("%d", edges[i].flow), flag = false;
    144                 else printf(" %d", edges[i].flow);
    145             }
    146         }
    147         printf("
    ");
    148     }
    149 }



  • 相关阅读:
    进程,线程,协程,异步IO知识点
    Socket网络编程知识点
    面向对象编程知识点
    Zabbix系列之七——添加磁盘IO监测
    WARNING: 'aclocal-1.14' is missing on your system.
    tomcat的catalina.out日志按自定义时间日式进行分割
    Plugin with id 'com.novoda.bintray-release' not found.的解决方案
    MaterialCalendarDialog【Material样式的日历对话框】
    导入项目报错【Minimum supported Gradle version is 3.3. Current version is 2.14.1】
    通过Calendar简单解析Date日期,获取年、月、日、星期的数值
  • 原文地址:https://www.cnblogs.com/titicia/p/4704427.html
Copyright © 2020-2023  润新知