uvalive 11865 Stream My Contest

题意:

有一个网络中心,和许多个城市,网络中心以及城市之间有若干条边,这些边有两个属性,最大带宽和修建费用。

现在要用最多不超过C的费用修建网络,使得每个城市都有网络连接,最大化最小带宽。

带宽限制是,一条边可以接受不大于自己最大值的带宽。

边是有向边unidirectional

思路:

最大化最小值,那么考虑到用二分,但是这题应该有一个隐藏条件,那就是带宽越大,修建费用越高,这样才满足二分的条件。

然后有向边,就用最小树形图的朱刘算法,复杂度为O(n^3),由于n的规模比较小,所以可以接受。

注意,需要先特判输入中的最小带宽是否满足要求

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <vector>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int N = 65;
  8 const int inf = 0x3f3f3f3f;
  9 
 10 int in[N],vis[N],pre[N],id[N];
 11 
 12 struct edge
 13 {
 14     int from,to,cost;
 15     
 16     edge(int a,int b,int c)
 17     {
 18         from = a;
 19         to = b;
 20         cost = c;
 21     }
 22 };
 23 
 24 struct node
 25 {
 26     int from,to,bd,cost;
 27     
 28     node(int a,int b,int c,int d)
 29     {
 30         from = a;
 31         to = b;
 32         bd = c;
 33         cost = d;
 34     }
 35 };
 36 
 37 vector<node> ns;
 38 vector<edge> es;
 39 
 40 int n,m,sumc;
 41 
 42 int meet(int lim)
 43 {
 44     es.clear();
 45     
 46     int root = 0;
 47     
 48     int res = 0;
 49     
 50     int tn = n;
 51     
 52     for (int i = 0;i < m;i++)
 53     {
 54         int a = ns[i].from,b = ns[i].to,c = ns[i].bd,d = ns[i].cost;
 55         
 56         if (c < lim) continue;
 57         
 58         es.push_back(edge(a,b,d));
 59     }
 60     
 61     while (1)
 62     {
 63         //printf("2333
");    
 64         
 65         memset(in,inf,sizeof(in));
 66         
 67         for (int i = 0;i < es.size();i++)
 68         {
 69             edge e = es[i];
 70             
 71             int to = e.to;
 72             
 73             if (e.from != e.to && e.cost < in[to])
 74             {
 75                 in[to] = e.cost;
 76                 pre[to] = e.from;
 77             }
 78         }
 79         
 80         for (int i = 0;i < tn;i++)
 81         {
 82             if (i != root && in[i] == inf)
 83                 return -1;
 84         }
 85         
 86         int cnt = 0;
 87         
 88         memset(id,-1,sizeof(id));
 89         memset(vis,-1,sizeof(vis));
 90         
 91         in[root] = 0;
 92         
 93         for (int i = 0;i < tn;i++)
 94         {
 95             res += in[i];
 96             
 97             int v = i;
 98             
 99             while (vis[v] != i && id[v] == -1 && v != root)
100             {
101                 vis[v] = i;
102                 v = pre[v];
103             }
104             
105             if (id[v] == -1 && v != root)
106             {
107                 for (int u = pre[v];u != v;u = pre[u])
108                 {
109                     id[u] = cnt;
110                 }
111                 
112                 id[v] = cnt++;
113             }
114         }
115         
116         if (cnt == 0) break;
117         
118         for (int i = 0;i < tn;i++)
119         {
120             if (id[i] == -1) id[i] = cnt++;
121         }
122         
123         for (int i = 0;i < es.size();i++)
124         {
125             int to = es[i].to;
126             
127             es[i].from = id[es[i].from];
128             es[i].to = id[es[i].to];
129             
130             if (es[i].from != es[i].to)
131             {
132                 es[i].cost -= in[to];
133             }
134         }
135         
136         root = id[root];
137         tn = cnt;
138     }
139     
140     if (res > sumc) return -1;
141     else return res;
142 }
143 
144 int main()
145 {
146     int t;
147     
148     scanf("%d",&t);
149     
150     while (t--)
151     {
152         scanf("%d%d%d",&n,&m,&sumc);
153         
154         ns.clear();
155         
156         int mnb = inf,mxb = 0;
157         
158         for (int i = 0;i < m;i++)
159         {
160             int a,b,c,d;
161             
162             scanf("%d%d%d%d",&a,&b,&c,&d);
163             
164             ns.push_back(node(a,b,c,d));
165             
166             mxb = max(mxb,c);
167             mnb = min(mnb,c);
168         }
169         
170         if (meet(mnb) == -1)
171         {
172             printf("streaming not possible.
");
173         }
174         else
175         {
176             while (mxb - mnb > 1)
177             {
178                 //printf("***
");
179                 int mid = (mxb + mnb) >> 1;
180                 
181                 if (meet(mid) != -1) mnb = mid;
182                 else mxb = mid - 1;
183             }
184             
185             while (meet(mnb+1) != -1) mnb++;
186             
187             printf("%d kbps
",mnb);
188         }
189     }
190     
191     return 0;
192 }
原文地址:https://www.cnblogs.com/kickit/p/8809006.html