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