差分约束系统。。。因为题目要求的是1和n的最大距离所以这题就跑最长路。。
对于互相反感的牛(i与j互相反感,彼此距离至少为len,i<j),就有dis[j]-dis[i]>=len。就加一条i->j,长度为len的边。
有好感的牛(i与j有好感,彼此距离至多len,i<j),就有dis[j]-dis[i]<=len;但因为我们跑的是最长路,所以得改成dis[i]-dis[j]>=-len的形式,就加一条j->i,长度-len的边。
又因为牛是按编号站成一列。。所以dis[i+1]-dis[i]>=0。也就是连一条i->i+1,长度为0的边(1<=i<n)。
如果有正权环的话就无解,如果从点n无法走到点1,也就是说n和1之间没有什么约束,那么1和n距离可以无穷大。。。
其实也可以把权值取反然后跑最短路。。虽然都一样= =
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=1023; 6 struct zs{ 7 int too,pre,dis; 8 }e[23333]; 9 int last[maxn],dis[maxn],dl[maxn],tot; 10 int i,n,m1,m2,a,b,c,l,r,now; 11 bool u[maxn],ins[maxn],flag; 12 int ra;char rx; 13 inline int read(){ 14 rx=getchar();ra=0; 15 while(rx<'0'||rx>'9')rx=getchar(); 16 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 17 } 18 inline void insert(int a,int b,int c){ 19 e[++tot].too=b;e[tot].dis=c;e[tot].pre=last[a];last[a]=tot; 20 } 21 void dfs(int x){ 22 ins[x]=1; 23 for(int i=last[x],to=e[i].too;i&&!flag;i=e[i].pre,to=e[i].too)if(dis[to]<dis[x]+e[i].dis){ 24 dis[to]=dis[x]+e[i].dis;if(ins[to]){flag=1;return;} 25 dfs(to); 26 } 27 ins[x]=0; 28 } 29 int main(){ 30 n=read();m1=read();m2=read(); 31 for(i=1;i<n;i++)insert(i,i+1,0); 32 for(i=1;i<=m1;i++){ 33 a=read();b=read();c=read(); 34 if(a>b)swap(a,b); 35 insert(b,a,-c); 36 } 37 for(i=1;i<=m2;i++){ 38 a=read();b=read();c=read();if(a>b)swap(a,b); 39 insert(a,b,c); 40 } 41 l=0;r=1;dl[1]=n;u[n]=1; 42 while(l<r){ 43 now=dl[++l]; 44 for(i=last[now];i;i=e[i].pre)if(!u[e[i].too]) 45 dl[++r]=e[i].too,u[e[i].too]=1; 46 } 47 if(!u[1]){puts("-2");return 0;} 48 memset(dis,188,sizeof(dis));dis[n]=0; 49 dfs(n); 50 if(flag){puts("-1");return 0;} 51 printf("%d ",-dis[1]); 52 return 0; 53 }
为啥dfs版的spfa会比kpm写的队列版慢20倍。。。。。。。。。。。也许是数据很少有无解情况吧。。