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; } }