hdu3268

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

这是一个最短路的问题,建立一个源点S,然后连接所有的点,边上的权值为最初的价钱p-1,可用来交易的物品建边,权值为R,然后价钱相等的物品建边,权值为0,求以S为源点的单源多点最短路,即可求出结果,第二问三重循环可求解,注意第二问循环的判断条件,勿让物品选重复。。。,这里wa了好久。。代码参考:

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

#define CLR(arr,v) memset(arr,v,sizeof(arr))

int m,n;
const int size = 50;
const int INS = INT_MAX/2;
int val[size],dis[size];
int h[size],ed[1000],nex[1000],price[1000],que[size],inque[size];
int pos,head,total;

void init()
{
    pos = 1;head = total = 0;
    CLR(h,0); CLR(que,0);  CLR(price,0);
    CLR(ed,0);CLR(inque,0);CLR(nex,0);
    fill(dis,dis+size,INS);CLR(val,0);
}
void add(int u,int v,int f)
{
    ed[pos] = v;
    price[pos] = f;
    nex[pos] = h[u];
    h[u] = pos++;
}

void SPFA()
{
    dis[0] = 0;
    que[total++] = 0;
    inque[0] = true;
    while(head < total)
    {
        int p = que[head];    
        inque[p] = false;
        head = (head+1)%size;
        for(int i = h[p]; i ;i = nex[i])
        {
            int to = ed[i];
            if(dis[to] > dis[p] + price[i])
            {
                dis[to] = dis[p] + price[i];
                if(!inque[to])
                {
                    que[total] = to;
                    inque[to] = true;
                    total = (total+1)%size;
                }
            }
        }
    }
    for(int i = 1;i <= n;++i)
    {
        printf("%d %d\n",i,dis[i]);
    }
    int cnt = 0; CLR(val,0);
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            for(int k = 1 + j;k <= n;++k)
                if(i != j && i != k && dis[i] == dis[k] + dis[j] && !val[i])
                {
                    val[i] = true;cnt++;
                }
    printf("%d\n",cnt);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        int b,money;
        for(int i = 1;i <= n;++i)
        {
            scanf("%d%d",&b,&money);
            val[b] = money;
            add(0,b,money-1);
        }
        scanf("%d",&m);
        int u,v,f;
        for(int i = 0;i < m;++i)
        {
            scanf("%d%d%d",&u,&v,&f);
            add(u,v,f);
        }
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= n;++j)
                if(i != j && val[i] == val[j])
                {
                    add(i,j,0);
                    add(j,i,0);
                }
        SPFA();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值