地址:http://acm.bit.edu.cn/mod/programming/view.php?a=511
题意:有一群牛编号从1到n依次沿直线排列,若两牛相互喜欢,则他们之间的距离不得大于给定值;若两牛相互讨厌,则他们之间的距离不得小于给定值;给出所有的喜欢和讨厌情况,问在这些约束条件下1牛到n牛的最大距离。
这类题是第一次接触,是差分约束问题,可以用spfa解。。具体的通用做法是,若最后求最大解(如本题),则将所有的约束不等式化成d[i]-d[j]<=t形式,对于每个不等式,添加从i到j的有向边,权值为t(如本题中牛互相讨厌的情况就要两边取相反数化成小于等于号形式),然后spfa求最短路。若有负权环(即spfa中点入队次数超过n-1次)说明条件有矛盾;若最后dis[n]为初始值则表明答案为无穷大;否则答案即为dis[n].而若最后求最小解,则应全部化成d[i]-d[j]>=t形式,然后spfa求最长路。
其原理见http://www.2cto.com/kf/201207/143735.html
继续坚持邻接矩阵不动摇。。
#include<iostream>
#include<queue>
using namespace std;
#define INF 0x7f7f7f7f
int map[1005][1005],dis[1005],flag[1005],vis[1005];
int main()
{
int n,ml,md,temp,i,T1,T2,T3;
memset(map,0x7f,sizeof(map));
memset(dis,0x7f,sizeof(dis));
memset(flag,0,sizeof(flag));
memset(vis,0,sizeof(vis));
dis[1]=0;
scanf("%d%d%d",&n,&ml,&md);
while(ml--) //建图
{
scanf("%d%d%d",&T1,&T2,&T3);
if(T1>T2) temp=T1,T1=T2,T2=temp;
if(T3<map[T1][T2]) map[T1][T2]=T3;
}
while(md--)
{
scanf("%d%d%d",&T1,&T2,&T3);
if(T1>T2) temp=T1,T1=T2,T2=temp;
if(-T3<map[T2][T1]) map[T2][T1]=-T3;
}
for(i=1;i<=n-1;i++) if(map[i+1][i]>0) map[i+1][i]=0; //隐藏条件,编号大的一定在后
queue <int>q; //spfa(注意用vis数组记录当前是否在队内,如果已经在队内就不能再次添加)
q.push(1);
vis[1]=1,flag[1]++;
while(!q.empty())
{
int now=q.front();
for(i=1;i<=n;i++)
{
if(dis[now]<INF&&map[now][i]<INF&&dis[i]>dis[now]+map[now][i])
{
dis[i]=dis[now]+map[now][i];
if(!vis[i])
{
if(flag[i]==n-1)
{
printf("-1\n");
return 0;
}
q.push(i);
vis[i]=1,flag[i]++;
}
}
}
q.pop();
vis[now]=0;
}
if(dis[n]==INF) printf("-2\n");
else printf("%d\n",dis[n]);
return 0;
}