题意分析
给出图,图中有边权为正的双向边和边权为负的单向边,求到某一点的值能否为负。
利用BellmanFord判断负环即可。
代码总览
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int nmax = 3000;
const int INF = 0x3f3f3f3f;
int dis[nmax];
struct Edge{
int to,nxt,val;
}edge[nmax<<1];
int head[nmax];
int tot = 0;
int t;
int n,w,m;
void add(int u, int v ,int w){
edge[tot].to = v;
edge[tot].nxt = head[u];
edge[tot].val = w;
head[u] = tot++;
}
void init(){
tot = 0;
memset(edge,0,sizeof edge);
memset(dis,0,sizeof dis);
memset(head,-1,sizeof head);
}
bool Bellman(){
for(int i = 1;i<=n;++i)
dis[i] = (i == 1? 0:INF);
for(int i = head[1];i!=-1;i=edge[i].nxt)
dis[edge[i].to] = min(dis[edge[i].to],edge[i].val);
for(int k = 2;k<=n;++k){
bool isupdate = false;
for(int i = 1;i<=n;++i){
for(int j = head[i];j!=-1;j = edge[j].nxt){
int to = edge[j].to;
// if(to == 1) continue;
if(dis[to] > dis[i] + edge[j].val)
dis[to] = dis[i] + edge[j].val,isupdate = true;
}
}
if(dis[1]<0) return true; // 夺命优化 172ms -> 32ms
if(!isupdate) return false;
}
for(int i = 1;i<=n;++i){
for(int j = head[i];j!=-1;j = edge[j].nxt){
int to = edge[i].to;
if(dis[to] > dis[j] + edge[j].val)
return true;
}
}
return false;
}
int main(){
scanf("%d",&t);
while(t--){
init();
scanf("%d %d %d",&n,&m,&w);
int a,b,t;
for(int i = 0;i<m;++i){
scanf("%d %d %d",&a,&b,&t);
add(a,b,t);
add(b,a,t);
}
for(int i = 0;i<w;++i){
scanf("%d %d %d",&a,&b,&t);
add(a,b,-t);
}
bool isok = Bellman();
if(isok) printf("YES\n");
else printf("NO\n");
}
return 0;
}