procedure2012
It's not worth it to know you're not worth it!

[关键字]:图论 最短路

[题目大意]:哥伦布需要买n件东西,每件东西可以通过如下四种方式:1、金币买。2、用一个玻璃珠(一共有无数个)代替一个金币再用金币买。3、等价的货物交换.4、用便宜的物品换再用金币买。问每件物品的最小价格以及有多少件物品的最小价格=其他两件物品价格和。

//==================================================================================

[分析]:首先2是必定要用的策略,所以把所有商品的初始价格都减一。然后对于每种4都要另一条边从便宜的到贵的权值是需要多加的金币数。这时有一个源点的问题,到底该把哪个个点作为源点,而且图也有可能不是连通的。我用的是直接把初始价格作为dis数组的初始值,然后Bellman-Ford……这样就无所谓了……还有一种作法就是新建源点然后源点到每个点的边权为初始值。

[代码]:

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=100;

struct node
{
int x,y,d;
}e[MAXN];
int d[MAXN];
int n,m,tot,ans;

void Add(int x,int y,int z)
{
++tot;
e[tot].x=x;
e[tot].y=y;
e[tot].d=z;
}

void Init()
{
scanf("%d",&n);
int x,y,z;
for (int i=1;i<=n;++i)
{
scanf("%d%d",&x,&y);
d[x]=y-1;
}
scanf("%d",&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
Add(x,y,z);
}
for (int i=1;i<n;++i)
for (int j=i+1;j<=n;++j)
if (d[i]==d[j]) Add(i,j,0),Add(j,i,0);
}

void Bellman()
{
bool f;
for (int i=1;i<=n;++i)
{
f=1;
for (int j=1;j<=tot;++j)
if (d[e[j].y]>d[e[j].x]+e[j].d)
{
f=0;
d[e[j].y]=d[e[j].x]+e[j].d;
}
if (f) break;
}
for (int i=1;i<=n;++i) printf("%d %d\n",i,d[i]);
}

void Solve()
{
Bellman();
bool f;
for (int i=1;i<=n;++i)
{
f=0;
for (int j=1;j<=n;++j)
if (i!=j)
for (int k=1;k<=n;++k)
if (i!=k && j!=k)
if (d[j]+d[k]==d[i]) f=1;
if (f) ++ans;
}
printf("%d\n",ans);
}

int main()
{
int test;
scanf("%d",&test);
while (test--)
{
tot=ans=0;
Init();
Solve();
}
return 0;
}



posted on 2012-03-15 00:30  procedure2012  阅读(248)  评论(0编辑  收藏  举报