这个题是判断有没有一条权值为负的回路,用SPFA是OK的,如果某个顶点重复入队列N次,就证明存在负权值回路。如果这个图是一个连通图,那么
任意选择一点开始搜都行,但是如果该图不连通,那么我认为从从所有虫洞的起点都搜一遍是个不错的选择。不过是不是我应该默认一个农场嘛,应该会是连通的。。。。。 但是我只从顶点1开始判断,也AC了,只是老感觉不严谨,也许是测试数据弱吧 希望能用邻接表存,邻接矩阵存的话,复杂度提高了,顶点有500个,边只有2500+200条,算稀疏图了吧 如果一定要用邻接矩阵存的话,注意一下重边的情形,选择时间花费最少的应该总是正确答案。
贴代码:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #define MAXN 505 5 #define INF 1000000 6 using namespace std; 7 struct ArcNode 8 { 9 int v,time; 10 } edge[MAXN][MAXN]; 11 int timemin[MAXN]; 12 bool s[MAXN]; 13 int n; 14 int arcnum[MAXN]; 15 int num[MAXN]; 16 bool SPFA(int vo) 17 { 18 int i,j; 19 queue<int>Q; 20 memset(num,0,sizeof(num)); 21 memset(s,false,sizeof(s)); 22 for(i=1; i<=n; i++) 23 timemin[i] = INF; 24 timemin[vo] = 0; 25 Q.push(vo); 26 s[vo] = true; 27 num[vo] = 1; 28 while(!Q.empty()) 29 { 30 for(j=1; j<=n ; j++) 31 if(num[j] > n) return true; 32 int t = Q.front(); 33 Q.pop(); 34 s[t] = false; 35 for(j=0; j< arcnum[t]; j++) 36 { 37 if(timemin[t] + edge[t][j].time < timemin[edge[t][j].v]) 38 { 39 timemin[edge[t][j].v] = timemin[t] + edge[t][j].time; 40 if(!s[edge[t][j].v]) 41 { 42 s[edge[t][j].v] = true; 43 Q.push(edge[t][j].v); 44 num[edge[t][j].v]++; 45 } 46 } 47 } 48 } 49 return false; 50 } 51 int main() 52 { 53 // freopen("in.cpp","r",stdin); 54 int f; 55 scanf("%d",&f); 56 while(f--) 57 { 58 int i,j; 59 int m,w; 60 scanf("%d%d%d",&n,&m,&w); 61 int u,v,time; 62 memset(arcnum,0,sizeof(arcnum)); 63 for(i=0; i<m; i++) 64 { 65 scanf("%d%d%d",&u,&v,&time); 66 edge[u][arcnum[u]].v = v; 67 edge[u][arcnum[u]].time = time; 68 arcnum[u]++; 69 edge[v][arcnum[v]].v = u; 70 edge[v][arcnum[v]].time = time; 71 arcnum[v]++; 72 } 73 int cur = 0; 74 int l[MAXN]; 75 for(i=0; i<w; i++) 76 { 77 scanf("%d%d%d",&u,&v,&time); 78 for(j=0; j < cur && l[j] != u; j++); 79 if(j == cur) l[cur++] = u; 80 edge[u][arcnum[u]].v = v; 81 edge[u][arcnum[u]++].time = -time; 82 } 83 for(i=0; i<cur; i++) 84 { 85 if(SPFA(l[i])) 86 { 87 printf("YES\n"); 88 break; 89 } 90 } 91 if(i == cur)printf("NO\n"); 92 } 93 return 0; 94 }