Columbus’s bargain (hdu3268 最短路

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

题意:有以下交换规则

1.用玻璃球抵掉1块钱(玻璃球有无数个  so 都可以-1)

2.等价的货物可以两两交换

3.可以用价格低的+相应的差价 交换到价格高的

给你n个商品的价格 

再给m行满足条件3的

 问:最少买这n件商品的钱分别是多少,还有 有多少种商品价格 可以等于另两种相加价格

 

题解:用最短路 

#include<bits/stdc++.h>
using namespace std;
int dis[30];
typedef pair<int,int>pai;
vector<pai>ve[30];
int n;
void dij()
{
    int i;
    for(i=1;i<=n;i++)dis[i]=0x3f3f3f3f;
    dis[0]=0;
    queue<int>qu;
    qu.push(0);
    while(!qu.empty())
    {
        int f=qu.front();
        qu.pop();
        for(int j=0;j<ve[f].size();j++)
        {
            if(dis[f]+ve[f][j].second<dis[ve[f][j].first])
            {
                dis[ve[f][j].first]=dis[f]+ve[f][j].second;
                qu.push(ve[f][j].first);//这里不小心把dis puah进去了
            }
        }
    }
}
int main()
{
    int i,j,m,t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        int q,p;
        int flag[30];
        memset(flag,0,sizeof(flag));
        for(i=0;i<=30;i++)ve[i].clear();//刚开始没有把ve【0】清空
        for(i=1;i<=n;i++)
        {
            cin>>q>>p;
            flag[q]=p;
            for(j=1;j<=n;j++)
            {
                if((j!=q)&&(flag[j]==p))
                {
                    ve[j].push_back(pai(q,0));//若有两个商品价格一样则可以连一条0的边
                                              //因为 若可以用更低的价格换j ,j和q价格一样 那么q也可以用j的价格换
                    ve[q].push_back(pai(j,0));
                }
            }
            ve[0].push_back(pai(q,p-1));//玻璃球换 so-1
        }
        cin>>m;
        while(m--)
        {
            int a,b,c;
            cin>>a>>b>>c;
            ve[a].push_back(pai(b,c));
        }
        dij();
        int dd[30];
        for(i=1;i<=n;i++)
        {
            cout<<i<<" "<<dis[i]<<endl;
            dd[i]=dis[i];
        }
        int k,sum=0;
        for(i=1;i<=n;i++)//这里要注意 是每个商品看过去 (看是否由其他两个相加可以得到他 可以的话+1
                             //但是 要是他可以由这两个商品相加得到  又可以由那两个商品相加得到  那只能算一次
        {
            bool bf=false;
            for(j=1;j<n;j++)
            {
                for(k=j+1;k<=n;k++)
                {
                    if(dd[i]==dd[j]+dd[k]&&i!=k&&i!=j&&bf==false)
                    {
                        sum++;
                        bf=true;
                        break;
                    }
                }
                if(bf)break;
            }
        }
     /*   map<int,int>mp;/
        mp.clear();
        sort(dd+1,dd+n+1);
        for(i=1;i<=n;i++)
        {
            for(j=i+1;j<=n;j++)
            {
                for(k=j+1;k<=n;k++)//这个是错的 因为k没有从1开始
                {
                    if(dd[i]+dd[j]==dd[k])
                    {
                        if(mp[dd[k]]==0)sum++,mp[dd[k]]=1;
                    }
                }
            }
        }*/
        cout<<sum<<endl;
    }
}

 

posted @ 2019-08-12 09:12  -第4题-  阅读(199)  评论(0编辑  收藏  举报