BZOJ 4349标题强行提示做法,样例和2260一样,出题人真是太懒了。。
发现对于某种物品,其购买量对方案是没有影响的,因此我们只考虑购买量为1的情况。建立虚点连向所有顶点,那么跑一次最小树形图即可。
另外购买量为0的点可以直接删了。
#include <cstdio>
#include <cstring>
#include <cmath>
#define ms(a,b) memset(a,b,sizeof(a))
#define FOR(i,j,k) for(int i=j;i<=k;++i)
const int N = 128, M = 10001;
void getmin(double &a, double b) { if (a > b) a = b; }
int u[M], v[M], id[N], vis[N], nav[N], count[N], fa[N];
double x[N], y[N], w[M], in[N], minc[N];
double edmonds(int rt, int n, int m) {
int i, a, b, cnt;
double ans = 0;
while (1) {
FOR(i,1,n) in[i] = 1e18;
FOR(i,1,m) if (w[i] < in[v[i]] && u[i] != v[i])
in[v[i]] = w[i], fa[v[i]] = u[i];
FOR(i,1,n) if (i != rt && in[i] == 1e18) return -1;
ms(id, 0); ms(vis, 0); in[rt] = 0; cnt = 0;
FOR(i,1,n) {
ans += in[i];
for (b = i; vis[b] != i && !id[b] && b != rt; b = fa[b]) vis[b] = i;
if (b != rt && !id[b]) {
++cnt;
for (a = fa[b]; a != b; a = fa[a]) id[a] = cnt;
id[b] = cnt;
}
}
if (!cnt) break;
FOR(i,1,n) if (!id[i]) id[i] = ++cnt;
FOR(i,1,m) {
int x = v[i];
u[i] = id[u[i]]; v[i] = id[v[i]];
if (u[i] != v[i]) w[i] -= in[x];
}
n = cnt; rt = id[rt];
}
return ans;
}
int main() {
int n, i, k, a, b, m = 0, graph_node; double c;
scanf("%d", &n);
FOR(i,1,n) {
scanf("%lf%d", &c, &count[i]);
if (count[i]) ++m, v[m] = m; nav[i] = m; minc[m] = w[m] = c;
}
graph_node = m + 1; FOR(i,1,m) u[i] = graph_node;
scanf("%d", &k);
FOR(i,1,k) {
scanf("%d%d%lf", &a, &b, &c);
if (count[a] && count[b]) {
u[++m] = nav[a], v[m] = nav[b];
getmin(minc[v[m]], w[m] = c);
}
}
double ans = edmonds(graph_node, graph_node, m);
FOR(i,1,n) if(count[i] > 1) ans += (count[i] - 1) * minc[nav[i]];
printf("%.2lf\n", ans);
return 0;
}
2260: 商店购物
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 163 Solved: 45
[Submit][Status][Discuss]
Description
Grant是一个个体户老板,他经营的小店因为其丰富的优惠方案深受附近居民的青睐,生意红火。小店的优惠方案十分简单有趣。Grant规定:在一次消费过程中,如果您在本店购买了精制油的话,您购买香皂时就可以享受2.00元/块的优惠价;如果您在本店购买了香皂的话,您购买可乐时就可以享受1.50元/听的优惠价……诸如此类的优惠方案就是说:如果您在本店购买了商品A的话,您就可以以P元/件的优惠价格购买商品B(购买的数量不限)。有趣的是,你需要购买同样一些商品,由于不同的购买顺序,Grant老板可能会叫你付不同数量的钱。比如你需要一块香皂(原价2.50元)、一瓶精制油(原价10.00元)、一听可乐(原价1.80元),如果你按照可乐,精制油,香皂这样的顺序购买的话,Grant老板会问你要13.80元;而如果你按照精制油,香皂,可乐这样的顺序购买的话,您只需付13.50元。
现在该村的居民请你编写一个程序,告诉你Grant小店商品的原价,所有优惠方案及所需的商品,计算至少需要花多少钱。不允许购买任何不需要的商品,即使这样做可能使花得钱更少。
Input
,第一行为一个整数n(1<=n<=50),表示Grant小店的商品种数。接下来是n行,其中第(i+1)行由一个实数Ci (0
Output
只有一个实数,表示最少需要花多少钱。输出实数须保留两位小数。
Sample Input
4
10.00 1
1.80 1
3.00 0
2.50 2
2
1 4 2.00
4 2 1.50
Sample Output
15.50
4349: 最小树形图
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 52 Solved: 19
[Submit][Status][Discuss]
Description
小C现在正要攻打科学馆腹地——计算机第三机房。而信息组的同学们已经建好了一座座堡垒,准备迎战。小C作为一种高度智慧的可怕生物,早已对同学们的信息了如指掌。
攻打每一个人的堡垒需要一个代价,而且必须攻打若干次才能把镇守之人灭得灰飞烟灭。
当小C在绞尽脑汁想攻打方案时,突然从XXX的堡垒中滚出来一个纸条:一个惊人的秘密被小C发现了:原来各个堡垒之间会相互提供援助,但是当一个堡垒被攻打时,他对所援助的堡垒的援助就会停止,因为他自己已经自身难保了。也就是说,小C只要攻打某个堡垒一次之后,某些堡垒就只需要花更小的代价攻击了。
现在,要你求消灭全机房要用掉代价最小多少。
Input
第一行一个数N,(N<=50),表示机房修建的堡垒数。
接下来N行,每行两个数,第一个实数Ai表示攻打i号堡垒需要的代价Ai(0
Output
一行,一个实数表示消灭全机房要用的最小代价,保留两位小数。
Sample Input
3
10.00 1
1.80 1
2.50 2
2
1 3 2.00
3 2 1.50
Sample Output
15.50