题目链接:( ̄▽ ̄)
思路:它的题意是判断有没有正权回路,起点没有规定是哪个点(没读清楚wa了n次, 不是从第一个点判断正权回路)
Ps:第一道spfa题~( ̄▽ ̄~)(~ ̄▽ ̄)~
code:
#include <stdio.h> #include <string.h> typedef struct { int v, next; double p; }node; node edge[10000]; int n = 0, used[40], visit[40], head[40], flag = 0; double dis[40]; char str[40][30], str1[40], str2[40]; int find(char *str1) { int i = 0; for(i = 0; i<n; i++) { if(strcmp(str[i], str1) == 0) return i; } return i; } void spfa(int k) { int i = 0, quene[1000], front = 0, rear = 0, cur = 0, item = 0; for(i = 0; i<n; i++)//每回都要初始化 { used[i] = visit[i] = 0; dis[i] = 0; } quene[rear++] = k; used[k] = 1; dis[k] = 1; while(front<rear) { cur = quene[front++];//cur为当前点 item = head[cur];//item为当前点在edge[]中邻边所存的信息 used[cur] = 0; while(item != -1) { if(dis[edge[item].v]<dis[cur]*edge[item].p)//可以进行松弛 { dis[edge[item].v] = dis[cur]*edge[item].p; if(visit[edge[item].v]>n+1)//一个点入队n次表明必存在回路 { flag = 1; return ; } if(!used[edge[item].v])//用used标记该点在不在队列中 { used[edge[item].v] = 1; visit[edge[item].v]++;//该点入队次数 quene[rear++] = edge[item].v; } } item = edge[item].next;//读取下一个邻边在edge[]中的位置 } } } int main() { int i = 0, m = 0, a = 0, b = 0, count = 0; double p = 0; while(scanf("%d",&n), n) { getchar(); flag = 0; for(i = 0; i<n; i++) { head[i] = -1; gets(str[i]); } scanf("%d",&m); getchar(); for(i = 0; i<m; i++) { scanf("%s",str1); scanf("%lf",&p); scanf("%s",str2); a = find(str1); b = find(str2); edge[i].v = b; edge[i].p = p; edge[i].next = head[a]; head[a] = i; } for(i = 0; i<n; i++)//以第i个顶点为起点, 看有没有正权回路 { if(!flag) spfa(i); } printf("Case %d: ",++count); if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }