传送门:BZOJ2330
题解
三角不等式?就是注意求最小值是跑最长路,最大值跑最短路,根据性质来。
还有判环。&没有必要建0点(还会T)
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=0x7fffffff;
const int N=2e6+10;
const int M=1e5+10;
int n,k,x,a,b;
int w[N],to[N],head[M],nxt[N],tot;
int d[M],vis[M],cir[M],upd[M];
ll ans;
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
inline void lk(int u,int v,int val)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=val;}
inline int spfa(int x)
{
queue<int>Q;
Q.push(x);vis[x]=true;cir[x]=1;upd[x]=1;
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i;i=nxt[i]){
if(d[to[i]]<d[now]+w[i]){
upd[to[i]]=1;//加在括号外就WA了
d[to[i]]=d[now]+w[i];
cir[to[i]]++;
if(cir[to[i]]>=n) return 0;
if(!vis[to[i]]){
vis[to[i]]=1;
Q.push(to[i]);
}
}
}
vis[now]=0;
}
return 1;
}
int main(){
n=rd();k=rd();
for(int i=1;i<=n;i++) d[i]=1;
while(k--){
x=rd();a=rd();b=rd();
switch(x){
case 1 :lk(a,b,0);lk(b,a,0);break;
case 2 :if(a==b){printf("-1\n");return 0;}lk(a,b,1);break;
case 3 :lk(b,a,0);break;
case 4 :if(a==b){printf("-1\n");return 0;}lk(b,a,1);break;
case 5 :lk(a,b,0);break;
}
}
for(int i=1;i<=n;i++){
if(!upd[i]){
if(!spfa(i)){
printf("-1\n");return 0;
}
}
}
for(int i=1;i<=n;i++) ans+=d[i];
printf("%lld\n",ans);
return 0;
}