最小奖励 MINAW

来源:互联网 发布:阿里云降低配置 编辑:程序博客网 时间:2024/04/29 06:41

【题目描述】

Jzabc更是一个狂热的“驴友”,这次他想去一个诡异的地方。这个地方有n个村庄,编号为1n。此刻他在1号村,他想到n号村。这n个村子之间有m条单向道路。通过某些道路时,可能需要花费一些钱作为“买路钱”,可是通过一些道路时不仅不用交钱反而会得到某些奖励。当然两个村庄之间可能有多条直接相连的道路,但是每条道路只能通过一次。这些村庄有这样的特性,从任何一个村庄出发,沿着任一条路径走都不会回到出发点。找到一条路径从1号到n号,他需要计算一共得到多少奖励,一共交了多少过路钱。如果奖励的钱数大于交的过路钱数,那么称这样一套路径可以得到奖励,反之吐过前者小雨后者,那么这样的路径需要花费,如果二者相等,那么Jzabc不会选择。不会出现所有的路径两者都相等,现在请你帮忙找到一条路径,使得到的奖励最小(为什么不是奖励最大?或花费最少?花费最大?),并输出最小奖励。如果找不到一条路径使其得到奖励,那么就找一条路径使其得到的花费最大(为何不是最小花费?),并输出最大花费。

【输入格式】

第一行,两个用空格隔开的正整数nm

以下m行,每行三个正整数x,y,w,描述一条路的信息,中间用空格隔开,其中x表示道路的起点,y表示终点;若w为负,则是通过磁条道路交的买路钱数目,若w为正,则表示这条路奖励的钱数;w不为零,且其绝对值不大于10

【输出格式】

一个整数,若有最小奖励则输出,否则输出最大花费;

【输入样例】

3 4

1 2 2

2 3 -1

2 3 3

1 3 -1

【输出样例】

1

【输入样例】

3 4

1 2 2

2 3 -3

2 3 -5

1 3 -2

【输出样例】

3

【数据规模】

对于20%的数据,满足n<=20,   m<=200

对于50%的数据,满足n<=50,   m<=2000

对于100%的数据,满足n<=100,   m<=20000



相当于有两问

1.能否得到奖励

2.如果能 求最小奖励

   如果不能 求最大花费


第一问 可以spfa求最长路 得到length[m]
若m<0 spfa求最短路 得到d[m]输出

若m>0 不好处理了就。。。

关于m>0 一开始是把每一个可能的与1的距离扔到set里

然后取出这些元素 更新与这个点相连的其他点的距离

这样可以过5个点 卡时可以全过


题解说可以拓扑排序+递推

后来加上拓扑排序+set 还是超5个点 1.5s左右

后来去掉set 用bool数组存可能的距离 就不超时了= =


其实由于数据太弱 直接spfa利用正权边求最短路就可以过了 (-.-)丧心病狂


附上拓扑排序代码 其中拓扑排序是我自己yy的 也不知道对不对...

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<set>using namespace std;const int inf=999999999;const int lim=108;const int len=20011;struct self{int x,y,w;}s[len];int first[len],nxt[len];bool inq[lim];queue<int>q;int longth[lim],d[lim];int m,n,a,b,c;void maxspfa(){    int a;    memset(inq,0,sizeof(inq));    for(a=1;a<=m;a++)longth[a]=-inf;    longth[1]=0;    q.push(1);    while(!q.empty())    {        int u=q.front();        q.pop();        inq[u]=0;        for(int e=first[u];e!=-1;e=nxt[e])        if(longth[s[e].y]<s[e].w+longth[u])        {            longth[s[e].y]=s[e].w+longth[u];            if(!inq[s[e].y])            {                inq[s[e].y]=1;                q.push(s[e].y);            }        }    }}void minspfa(){    int a;    memset(inq,0,sizeof(inq));    for(a=1;a<=m;a++)d[a]=inf;    d[1]=0;    q.push(1);    while(!q.empty())    {        int u=q.front();        q.pop();        inq[u]=0;        for(int e=first[u];e!=-1;e=nxt[e])        if(d[s[e].y]>d[u]+s[e].w)        {            d[s[e].y]=d[u]+s[e].w;            if(!inq[s[e].y])            {                inq[s[e].y]=1;                q.push(s[e].y);            }        }    }}int rank[lim],into[lim];void tsort(){    int i=0;    q.push(1);    while(!q.empty())    {        int u=q.front();q.pop();        i++;rank[i]=u;        for(int e=first[u];e!=-1;e=nxt[e])        {            into[s[e].y]--;            if(into[s[e].y]==0)            q.push(s[e].y);        }    }}bool g[lim][len];void work(){    int a,i;    for(a=1;a<=m;a++)q.push(rank[a]);    g[1][10000]=1;    while(!q.empty())    {        int u=q.front();q.pop();        for(int e=first[u];e!=-1;e=nxt[e])        {            for(i=0;i<=20000;i++)            if(g[u][i])g[s[e].y][i+s[e].w]=1;        }    }    for(i=10001;i<=20000;i++)    if(g[m][i])    {        printf("%d\n",i-10000);        return;    }}    int main(){    freopen("minaw.in","r",stdin);freopen("minaw.out","w",stdout);    memset(first,-1,sizeof(first));memset(nxt,-1,sizeof(nxt));    scanf("%d%d",&m,&n);    for(a=1;a<=n;a++)    {        scanf("%d%d%d",&s[a].x,&s[a].y,&s[a].w);        into[s[a].y]++;        nxt[a]=first[s[a].x];        first[s[a].x]=a;    }    maxspfa();    if(longth[m]<=0)    {        minspfa();        cout<<-d[m]<<endl;        return 0;    }    else    {        tsort();        work();    }    return 0;}        



原创粉丝点击