题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=2330
思路
刚开始看这题就想到用SPFA之类的求求最短路啥的,但是没有很清晰的思路,翻了题解才发现这是一个很裸的差分约束系统的题(不会差分约束系统的话比赛时就要GG啊)。
对于每个限制条件,在差分约束系统中我们都能把它们表示成
x−y<=a
的形式,从
y
向
于是我们就可以对题目数据中给出的每个限制条件建立一个图了,我们需要做的就是用SPFA求出这个图的最长路,但是这个最长路也是非常特殊的,对于任意点
i
而言,除了
为什么是这样呢?注意到一条指向点
i
的路径就是形如
另外就是特判的问题,差分约束系统的特判要讲究技巧,由于上面我们要求的是最长路,因此若图中有正环就无解(若题目要求最短路,则有负环就无解),这个可以通过SPFA实现,而在输入数据时,形如
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define MAXE 210000 //!!!!!!
#define MAXV 110000
using namespace std;
typedef long long int LL;
int n,k;
struct edge
{
int u,v,w,next;
}edges[MAXE];
int head[MAXV],nCount=0;
void AddEdge(int U,int V,int W)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].w=W;
edges[nCount].next=head[U];
head[U]=nCount; //!!!!!
}
int dist[MAXV],vis[MAXE];
bool inQueue[MAXV];
queue<int>q;
bool SPFA()
{
while(!q.empty())
{
int u=q.front();
q.pop();
inQueue[u]=false;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(dist[u]+edges[p].w>dist[v])
{
dist[v]=dist[u]+edges[p].w;
vis[p]++;
if(vis[p]>n) return false; //某条边的访问次数大于n,则说明出现了正环,有正环就不存在最长路,无解
if(!inQueue[v])
{
inQueue[v]=true;
q.push(v);
}
}
}
}
return true;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
int op,u,v;
scanf("%d%d%d",&op,&u,&v);
if(op==1) //u==v
AddEdge(u,v,0),AddEdge(v,u,0);
else if(op==2) //u<v
{
if(u==v) //特判
{
printf("-1");
return 0; //!!!!!!
}
AddEdge(u,v,1);
}
else if(op==3) //u>=v
AddEdge(v,u,0);
else if(op==4) //u>v
{
if(u==v) //特判
{
printf("-1");
return 0;
}
AddEdge(v,u,1);
}
else //u<=v
AddEdge(u,v,0);
}
for(int i=1;i<=n;i++)
{
dist[i]=1; //每个人必须都有糖果
inQueue[i]=true;
q.push(i);
}
LL ans=0;
if(!SPFA())
{
printf("-1\n");
return 0;
}
for(int i=1;i<=n;i++) ans+=dist[i];
printf("%lld\n",ans);
return 0;
}