这题调了有24小时。。。重写了N遍。。。最后被别人发现是数组开小了。。。= =。。。算了,,全当练习手速了。。。
思路:利用SPFA判断是否存在负圈
题目描述与实际数据不大相符,按照题目描述应当是从任意点出发的连通分支是否存在负圈,而实际上只要判断从第一个点出发是否构成负圈就足够了。。可能是数据强度不够。。
#include <stdio.h>
#include <string.h>
#define MAXN 1025
#define inf 100000000
int head[MAXN],next[MAXN*MAXN],pnt[MAXN*MAXN],length[MAXN*MAXN];
int tot;
int dist[MAXN];
int queue[1000000];
int qhead,qtail;
int inqueue[MAXN];
int countq[MAXN];
int n,m,w;
int a,b,len;
void addedge(int a,int b,int len)
{
pnt[tot]=b;
length[tot]=len;
next[tot]=head[a];
head[a]=tot++;
}
int spfa(int src)
{
qhead=0;
qtail=1;
for (int i=0; i<n; i++) {
dist[i]=inf;
}
memset(countq,0,sizeof(countq));
memset(inqueue,0,sizeof(inqueue));
dist[src]=0;
queue[qhead]=src;
inqueue[queue[qhead]]=1;
countq[queue[qhead]]++;
while (qhead<qtail) {
int idx=head[queue[qhead]];
while (~idx) {
if (dist[pnt[idx]] > dist[queue[qhead]]+length[idx]) {
dist[pnt[idx]] = dist[queue[qhead]]+length[idx];
if(!inqueue[pnt[idx]]) {
inqueue[pnt[idx]]=1;
countq[pnt[idx]]++;
if(countq[pnt[idx]]>n+1) return 1;
queue[qtail++]=pnt[idx];
}
}
idx=next[idx];
}
inqueue[queue[qhead]]=0;
qhead++;
}
return 0;
}
int main()
{
int ncase;
scanf("%d",&ncase);
while (ncase--) {
tot=0;
memset(head,-1,sizeof(head));
memset(next,-1,sizeof(next));
scanf("%d%d%d",&n,&m,&w);
for(int i=0; i<m; i++) {
scanf("%d%d%d",&a,&b,&len);
addedge(a-1,b-1,len);
addedge(b-1,a-1,len);
}
for(int i=0; i<w; i++) {
scanf("%d%d%d",&a,&b,&len);
addedge(a-1,b-1,-len);
}
//for(int i=0; i<n; i++) {
// addedge(n,i,0);
//}
//for (int i=0; i<=n; i++) {
// int idx=head[i];
// while (~idx) {
// printf("%d->%d:%d\n",i,pnt[idx],length[idx]);
// idx=next[idx];
// }
//}
int ans=0;
if(spfa(0)) ans=1;
if(ans) printf("YES\n");
else printf("NO\n");
//for (int i=0; i<=n; i++) {
// printf("%d %d\n",i,dist[i]);
//}
}
}
PS,如果按照之前的题意理解来做的话,可以建超级源点、
浙公网安备 33010602011771号